/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <security/pam_modutil.h>

#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>

/*
 * This module is intended to save password of  special group user
 *
 */

#define MAX_SPEC_GRP_PASS_LENGTH 20
#define MAX_SPEC_GRP_USER_LENGTH 16
#define MAX_KEY_SIZE 8
#define DEFAULT_SPEC_PASS_FILE "/etc/ipmi_pass"
#define META_PASSWD_SIG "=OPENBMC="
#define block_round(ODD, BLK)                                                  \
	((ODD) + (((BLK) - ((ODD) & ((BLK)-1))) & ((BLK)-1)))

/*
 * Meta data struct for storing the encrypted password file
 * Note: Followed by this structure, the real data of hash, iv, encrypted data
 * with pad and mac are stored.
 * Decrypted data will hold user name & password for every new line with format
 * like <user name>:<password>\n
 */
typedef struct metapassstruct {
	char signature[10];
	unsigned char reseved[2];
	size_t hashsize;
	size_t ivsize;
	size_t datasize;
	size_t padsize;
	size_t macsize;
} metapassstruct;

/**
 * @brief to acquire lock for atomic operation
 * Internally uses lckpwdf to acquire the lock. Tries to acquire the lock
 * using lckpwdf() in interval of 1ms, with maximum of 100 attempts.
 *
 * @return PAM_SUCCESS for success / PAM_AUTHTOK_LOCK_BUSY for failure
 */
int lock_pwdf(void)
{
	int i;
	int retval;

	i = 0;
	while ((retval = lckpwdf()) != 0 && i < 100) {
		usleep(1000);
		i++;
	}
	if (retval != 0) {
		return PAM_AUTHTOK_LOCK_BUSY;
	}
	return PAM_SUCCESS;
}

/**
 * @brief unlock the acquired lock
 * Internally uses ulckpwdf to release the lock
 */
void unlock_pwdf(void)
{
	ulckpwdf();
}

/**
 * @brief to get argument value of option
 * Function to get the value of argument options.
 *
 * @param[in] pamh - pam handle
 * @param[in] option - argument option to which value has to returned
 * @param[in] argc - argument count
 * @param[in] argv - array of arguments
 */
static const char *get_option(const pam_handle_t *pamh, const char *option,
			      int argc, const char **argv)
{
	int i;
	size_t len;

	len = strlen(option);

	for (i = 0; i < argc; ++i) {
		if (strncmp(option, argv[i], len) == 0) {
			if (argv[i][len] == '=') {
				return &argv[i][len + 1];
			}
		}
	}
	return NULL;
}

/**
 * @brief encrypt or decrypt function
 * Function which will do the encryption or decryption of the data.
 *
 * @param[in] pamh - pam handle.
 * @param[in] isencrypt - encrypt or decrypt option.
 * @param[in] cipher - EVP_CIPHER to be used
 * @param[in] key - key which has to be used in EVP_CIPHER api's.
 * @param[in] keylen - Length of the key.
 * @param[in] iv - Initialization vector data, used along with key
 * @param[in] ivlen - Length of IV.
 * @param[in] inbytes - buffer which has to be encrypted or decrypted.
 * @param[in] inbyteslen - length of input buffer.
 * @param[in] outbytes - buffer to store decrypted or encrypted data.
 * @param[in] outbyteslen - length of output buffer
 * @param[in/out] mac - checksum to cross verify. Will be verified for decrypt
 * and returns for encrypt.
 * @param[in/out] maclen - length of checksum
 * @return - 0 for success -1 for failures.
 */
int encrypt_decrypt_data(const pam_handle_t *pamh, int isencrypt,
			 const EVP_CIPHER *cipher, const char *key,
			 size_t keylen, const char *iv, size_t ivlen,
			 const char *inbytes, size_t inbyteslen, char *outbytes,
			 size_t *outbyteslen, char *mac, size_t *maclen)
{
	EVP_CIPHER_CTX *ctx;
	const EVP_MD *digest;
	size_t outEVPlen = 0;
	int retval = 0;
	size_t outlen = 0;

	if (cipher == NULL || key == NULL || iv == NULL || inbytes == NULL
	    || outbytes == NULL || mac == NULL || inbyteslen == 0
	    || EVP_CIPHER_key_length(cipher) > keylen
	    || EVP_CIPHER_iv_length(cipher) > ivlen) {
		pam_syslog(pamh, LOG_DEBUG, "Invalid inputs");
		return -1;
	}

	digest = EVP_sha256();
	if (!isencrypt) {
		char calmac[EVP_MAX_MD_SIZE];
		size_t calmaclen = 0;
		// calculate MAC for the encrypted message.
		if (NULL
		    == HMAC(digest, key, keylen, inbytes, inbyteslen, calmac,
			    &calmaclen)) {
			pam_syslog(pamh, LOG_DEBUG,
				   "Failed to verify authentication %d",
				   retval);
			return -1;
		}
		if (!((calmaclen == *maclen)
		      && (memcmp(calmac, mac, calmaclen) == 0))) {
			pam_syslog(pamh, LOG_DEBUG,
				   "Authenticated message doesn't match %d, %d",
				   calmaclen, *maclen);
			return -1;
		}
	}

	ctx = EVP_CIPHER_CTX_new();
	EVP_CIPHER_CTX_set_padding(ctx, 1);

	// Set key & IV
	retval = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, isencrypt);
	if (!retval) {
		pam_syslog(pamh, LOG_DEBUG, "EVP_CipherInit_ex failed with %d",
			   retval);
		EVP_CIPHER_CTX_free(ctx);
		return -1;
	}
	if ((retval = EVP_CipherUpdate(ctx, outbytes + outlen, &outEVPlen,
				       inbytes, inbyteslen))) {
		outlen += outEVPlen;
		if ((retval = EVP_CipherFinal(ctx, outbytes + outlen,
					      &outEVPlen))) {
			outlen += outEVPlen;
			*outbyteslen = outlen;
		} else {
			pam_syslog(pamh, LOG_DEBUG,
				   "EVP_CipherFinal returns with %d", retval);
			EVP_CIPHER_CTX_free(ctx);
			return -1;
		}
	} else {
		pam_syslog(pamh, LOG_DEBUG, "EVP_CipherUpdate returns with %d",
			   retval);
		EVP_CIPHER_CTX_free(ctx);
		return -1;
	}
	EVP_CIPHER_CTX_free(ctx);

	if (isencrypt) {
		// Create MAC for the encrypted message.
		if (NULL
		    == HMAC(digest, key, keylen, outbytes, *outbyteslen, mac,
			    maclen)) {
			pam_syslog(pamh, LOG_DEBUG,
				   "Failed to create authentication %d",
				   retval);
			return -1;
		}
	}
	return 0;
}


/**
 * @brief get temporary file handle
 * Function to get the temporary file handle, created using mkstemp
 *
 * @param[in] pamh - pam handle.
 * @param[in/out] tempfilename - tempfilename, which will be used in mkstemp.
 * @return - FILE handle for success. NULL for failure
 */
FILE * get_temp_file_handle(const pam_handle_t *pamh, char * const tempfilename)
{
	FILE *tempfile = NULL;
	int fd = -1;
	int oldmask = umask(077);
	fd = mkstemp(tempfilename);
	if (fd == -1) {
		pam_syslog(pamh, LOG_DEBUG, "Error in creating temp file");
		umask(oldmask);
		return NULL;
	}
	pam_syslog(pamh, LOG_DEBUG, "Temporary file name is %s", tempfilename);

	tempfile = fdopen(fd, "w");
	umask(oldmask);
	return tempfile;
}


/**
 * @brief updates special password file
 * Function to update the special password file. Stores the password against
 * username in encrypted form along with meta data
 *
 * @param[in] pamh - pam handle.
 * @param[in] keyfilename - file name where key seed is stored.
 * @param[in] filename - special password file name
 * @param[in] forwho - name of the user
 * @param[in] towhat - password that has to stored in encrypted form
 * @return - PAM_SUCCESS for success or PAM_AUTHTOK_ERR for failure
 */
int update_pass_special_file(const pam_handle_t *pamh, const char *keyfilename,
			     const char *filename, const char *forwho,
			     const char *towhat)
{
	struct stat st;
	FILE *pwfile = NULL, *opwfile = NULL, *keyfile = NULL;
	int err = 0, wroteentry = 0;
	char tempfilename[1024];
	size_t forwholen = strlen(forwho);
	size_t towhatlen = strlen(towhat);
	char keybuff[MAX_KEY_SIZE] = {0};
	size_t keybuffsize = sizeof(keybuff);

	const EVP_CIPHER *cipher = EVP_aes_128_cbc();
	const EVP_MD *digest = EVP_sha256();

	char *linebuff = NULL, *opwfilebuff = NULL, *opwptext = NULL;
	size_t opwptextlen = 0, opwfilesize = 0;
	metapassstruct *opwmp = NULL;

	char *pwptext = NULL, *pwctext = NULL;
	size_t pwctextlen = 0, pwptextlen = 0, maclen = 0;
	size_t writtensize = 0, keylen = 0;
	metapassstruct pwmp = {META_PASSWD_SIG, {0, 0}, .0, 0, 0, 0, 0};
	char mac[EVP_MAX_MD_SIZE] = {0};
	unsigned char key[EVP_MAX_KEY_LENGTH];
	char iv[EVP_CIPHER_iv_length(cipher)];
	char hash[EVP_MD_block_size(digest)];

	// Following steps are performed in this function.
	// Step 1: Create a temporary file - always update temporary file, and
	// then swap it with original one, only if everything succeded at the end.
	// Step 2: If file already exists, read the old file and decrypt it in buffer
	// Step 3: Copy user/password pair from old buffer to new buffer,
	// and update, if the user already exists with the new password
	// Step 4: Encrypt the new buffer and write it to the temp file created
	// at Step 1.
	// Step 5. rename the temporary file name as special password file.

	// verify the tempfilename buffer is enough to hold
	// filename_XXXXXX (+1 for null).
	if (strlen(filename)
	    > (sizeof(tempfilename) - strlen("__XXXXXX") - 1)) {
		pam_syslog(pamh, LOG_DEBUG, "Not enough buffer, bailing out");
		return PAM_AUTHTOK_ERR;
	}
	// Fetch the key from key file name.
	keyfile = fopen(keyfilename, "r");
	if (keyfile == NULL) {
		pam_syslog(pamh, LOG_DEBUG, "Unable to open key file %s",
			   keyfilename);
		return PAM_AUTHTOK_ERR;
	}
	if (fread(keybuff, 1, keybuffsize, keyfile) != keybuffsize) {
		pam_syslog(pamh, LOG_DEBUG, "Key file read failed");
		fclose(keyfile);
		return PAM_AUTHTOK_ERR;
	}
	fclose(keyfile);

	// Step 1: Try to create a temporary file, in which all the update will happen
	// then it will be renamed to the original file. This is done to have
	// atomic operation.
	snprintf(tempfilename, sizeof(tempfilename), "%s__XXXXXX", filename);
	pwfile = get_temp_file_handle(pamh, tempfilename);
	if (pwfile == NULL) {
		err = 1;
		goto done;
	}

	// Update temporary file stat by reading the special password file
	opwfile = fopen(filename, "r");
	if (opwfile != NULL) {
		if (fstat(fileno(opwfile), &st) == -1) {
			fclose(opwfile);
			fclose(pwfile);
			err = 1;
			goto done;
		}
	} else { // Create with this settings if file is not present.
		memset(&st, 0, sizeof(st));
		st.st_mode = 0x8000 | S_IRUSR;
	}
	if ((fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) ||
	    (fchmod(fileno(pwfile), st.st_mode) == -1)) {
		if (opwfile != NULL) {
			fclose(opwfile);
		}
		fclose(pwfile);
		err = 1;
		goto done;
	}
	opwfilesize = st.st_size;

	// Step 2: Read existing special password file and decrypt the data.
	if (opwfilesize) {
		opwfilebuff = malloc(opwfilesize);
		if (opwfilebuff == NULL) {
			fclose(opwfile);
			fclose(pwfile);
			err = 1;
			goto done;
		}

		if (fread(opwfilebuff, 1, opwfilesize, opwfile)) {
			opwmp = (metapassstruct *)opwfilebuff;
			opwptext = malloc(opwmp->datasize + opwmp->padsize);
			if (opwptext == NULL) {
				free(opwfilebuff);
				fclose(opwfile);
				fclose(pwfile);
				err = 1;
				goto done;
			}
			// User & password pairs are mapped as <user name>:<password>\n.
			// Add +3 for special chars ':', '\n' and '\0'.
			pwptextlen = opwmp->datasize + forwholen + towhatlen + 3
				     + EVP_CIPHER_block_size(cipher);
			pwptext = malloc(pwptextlen);
			if (pwptext == NULL) {
				free(opwptext);
				free(opwfilebuff);
				fclose(opwfile);
				fclose(pwfile);
				err = 1;
				goto done;
			}

			// First get the hashed key to decrypt
			HMAC(digest, keybuff, keybuffsize,
			     opwfilebuff + sizeof(*opwmp), opwmp->hashsize, key,
			     &keylen);

			// Skip decryption if there is no data
			if (opwmp->datasize != 0) {
				// Do the decryption
				if (encrypt_decrypt_data(
					    pamh, 0, cipher, key, keylen,
					    opwfilebuff + sizeof(*opwmp)
					    + opwmp->hashsize,
					    opwmp->ivsize,
					    opwfilebuff + sizeof(*opwmp)
					    + opwmp->hashsize
					    + opwmp->ivsize,
					    opwmp->datasize + opwmp->padsize,
					    opwptext, &opwptextlen,
					    opwfilebuff + sizeof(*opwmp)
					    + opwmp->hashsize
					    + opwmp->ivsize
					    + opwmp->datasize
					    + opwmp->padsize,
					    &opwmp->macsize)
				    != 0) {
					pam_syslog(pamh, LOG_DEBUG,
						   "Decryption failed");
					free(pwptext);
					free(opwptext);
					free(opwfilebuff);
					fclose(opwfile);
					fclose(pwfile);
					err = 1;
					goto done;
				}
			}

			// NULL terminate it, before using it in strtok().
			opwptext[opwmp->datasize] = '\0';

			linebuff = strtok(opwptext, "\n");
			// Step 3: Copy the existing user/password pair
			// to the new buffer, and update the password if user
			// already exists.
			while (linebuff != NULL) {
				if ((!strncmp(linebuff, forwho, forwholen))
				    && (linebuff[forwholen] == ':')) {
					writtensize += snprintf(
							       pwptext + writtensize,
							       pwptextlen - writtensize,
							       "%s:%s\n", forwho, towhat);
					wroteentry = 1;
				} else {
					writtensize += snprintf(
							       pwptext + writtensize,
							       pwptextlen - writtensize,
							       "%s\n", linebuff);
				}
				linebuff = strtok(NULL, "\n");
			}
		}
		// Clear the old password related buffers here, as we are done
		// with it.
		free(opwfilebuff);
		free(opwptext);
	} else {
		pwptextlen = forwholen + towhatlen + 3
			     + EVP_CIPHER_block_size(cipher);
		pwptext = malloc(pwptextlen);
		if (pwptext == NULL) {
			if (opwfile != NULL) {
				fclose(opwfile);
			}
			fclose(pwfile);
			err = 1;
			goto done;
		}
	}

	if (opwfile != NULL) {
		fclose(opwfile);
	}

	if (wroteentry) {
		// user password pair already updated,  round it off as per the CIPHER block
		pwptextlen =
			block_round(writtensize, EVP_CIPHER_block_size(cipher));
		// memset the padding bytes
		memset(pwptext + writtensize, 0, pwptextlen - writtensize);
	} else {
		// Write the new user:password pair at the end and round it off as per the
		// CIPHER block.
		writtensize += snprintf(pwptext + writtensize,
					pwptextlen - writtensize, "%s:%s\n",
					forwho, towhat);
		pwptextlen =
			block_round(writtensize, EVP_CIPHER_block_size(cipher));
		// memset the padding bytes
		memset(pwptext + writtensize, 0, pwptextlen - writtensize);
	}

	// Step 4: Encrypt the data and write to the temporary file
	if (RAND_bytes(hash, EVP_MD_block_size(digest)) != 1) {
		pam_syslog(pamh, LOG_DEBUG,
			   "Hash genertion failed, bailing out");
		free(pwptext);
		fclose(pwfile);
		err = 1;
		goto done;
	}

	// Generate hash key, which will be used for encryption.
	HMAC(digest, keybuff, keybuffsize, hash, EVP_MD_block_size(digest), key,
	     &keylen);
	// Generate IV values
	if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) {
		pam_syslog(pamh, LOG_DEBUG,
			   "IV generation failed, bailing out");
		free(pwptext);
		fclose(pwfile);
		err = 1;
		goto done;
	}

	// Buffer to store encrypted message.
	pwctext = malloc(pwptextlen + EVP_CIPHER_block_size(cipher));
	if (pwctext == NULL) {
		pam_syslog(pamh, LOG_DEBUG, "Ctext buffer failed, bailing out");
		free(pwptext);
		fclose(pwfile);
		err = 1;
		goto done;
	}

	// Do the encryption
	if (encrypt_decrypt_data(pamh, 1, cipher, key, keylen, iv,
				 EVP_CIPHER_iv_length(cipher), pwptext,
				 pwptextlen, pwctext, &pwctextlen, mac, &maclen)
	    != 0) {
		pam_syslog(pamh, LOG_DEBUG, "Encryption failed");
		free(pwctext);
		free(pwptext);
		fclose(pwfile);
		err = 1;
		goto done;
	}

	// Update the meta password structure.
	pwmp.hashsize = EVP_MD_block_size(digest);
	pwmp.ivsize = EVP_CIPHER_iv_length(cipher);
	pwmp.datasize = writtensize;
	pwmp.padsize = pwctextlen - writtensize;
	pwmp.macsize = maclen;

	// Write the meta password structure, followed by hash, iv, encrypted
	// data & mac.
	if (fwrite(&pwmp, 1, sizeof(pwmp), pwfile) != sizeof(pwmp)) {
		pam_syslog(pamh, LOG_DEBUG, "Error in writing meta data");
		err = 1;
	}
	if (fwrite(hash, 1, pwmp.hashsize, pwfile) != pwmp.hashsize) {
		pam_syslog(pamh, LOG_DEBUG, "Error in writing hash data");
		err = 1;
	}
	if (fwrite(iv, 1, pwmp.ivsize, pwfile) != pwmp.ivsize) {
		pam_syslog(pamh, LOG_DEBUG, "Error in writing IV data");
		err = 1;
	}
	if (fwrite(pwctext, 1, pwctextlen, pwfile) != pwctextlen) {
		pam_syslog(pamh, LOG_DEBUG, "Error in encrypted data");
		err = 1;
	}
	if (fwrite(mac, 1, maclen, pwfile) != maclen) {
		pam_syslog(pamh, LOG_DEBUG, "Error in writing MAC");
		err = 1;
	}

	free(pwctext);
	free(pwptext);

	if (fflush(pwfile) || fsync(fileno(pwfile))) {
		pam_syslog(
			pamh, LOG_DEBUG,
			"fflush or fsync error writing entries to special file: %s",
			tempfilename);
		err = 1;
	}

	if (fclose(pwfile)) {
		pam_syslog(pamh, LOG_DEBUG,
			   "fclose error writing entries to special file: %s",
			   tempfilename);
		err = 1;
	}

done:
	if (!err) {
		// Step 5: Rename the temporary file as special password file.
		if (!rename(tempfilename, filename)) {
			pam_syslog(pamh, LOG_DEBUG,
				   "password changed for %s in special file",
				   forwho);
		} else {
			err = 1;
		}
	}

	// Clear out the key buff.
	memset(keybuff, 0, keybuffsize);

	if (!err) {
		return PAM_SUCCESS;
	} else {
		unlink(tempfilename);
		return PAM_AUTHTOK_ERR;
	}
}


/* Password Management API's */

/**
 * @brief pam_sm_chauthtok API
 * Function which will be called for pam_chauthtok() calls.
 *
 * @param[in] pamh - pam handle
 * @param[in] flags - pam calls related flags
 * @param[in] argc - argument counts / options
 * @param[in] argv - array of arguments / options
 * @return - PAM_SUCCESS for success, others for failure
 */
int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	int retval = -1;
	const void *item = NULL;
	const char *user = NULL;
	const char *pass_new = NULL, *pass_old = NULL;
	const char *spec_grp_name =
		get_option(pamh, "spec_grp_name", argc, argv);
	const char *spec_pass_file =
		get_option(pamh, "spec_pass_file", argc, argv);
	const char *key_file = get_option(pamh, "key_file", argc, argv);


	if (spec_grp_name == NULL || key_file == NULL) {
		return PAM_IGNORE;
	}
	if (flags & PAM_PRELIM_CHECK) {
		// send success to verify other stacked modules prelim check.
		return PAM_SUCCESS;
	}

	retval = pam_get_user(pamh, &user, NULL);
	if (retval != PAM_SUCCESS) {
		return retval;
	}

	// get  already read password by the stacked pam module
	// Note: If there are no previous stacked pam module which read
	// the new password, then return with AUTHTOK_ERR

	retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
	if (retval != PAM_SUCCESS || item == NULL) {
		return PAM_AUTHTOK_ERR;
	}
	pass_new = item;

	struct group *grp;
	int spec_grp_usr = 0;
	// Verify whether the user belongs to special group.
	grp = pam_modutil_getgrnam(pamh, spec_grp_name);
	if (grp != NULL) {
		while (*(grp->gr_mem) != NULL) {
			if (strcmp(user, *grp->gr_mem) == 0) {
				spec_grp_usr = 1;
				break;
			}
			(grp->gr_mem)++;
		}
	}

	pam_syslog(pamh, LOG_DEBUG, "User belongs to special grp: %x",
		   spec_grp_usr);

	if (spec_grp_usr) {
		// verify the new password is acceptable.
		if (strlen(pass_new) > MAX_SPEC_GRP_PASS_LENGTH
		    || strlen(user) > MAX_SPEC_GRP_USER_LENGTH) {
			pam_syslog(
				pamh, LOG_ERR,
				"Password length (%x) / User name length (%x) not acceptable",
				strlen(pass_new), strlen(user));
			pass_new = NULL;
			return PAM_NEW_AUTHTOK_REQD;
		}
		if (spec_pass_file == NULL) {
			spec_pass_file = DEFAULT_SPEC_PASS_FILE;
			pam_syslog(
				pamh, LOG_ERR,
				"Using default special password file name :%s",
				spec_pass_file);
		}
		if (retval = lock_pwdf()) {
			pam_syslog(
				pamh, LOG_ERR,
				"Failed to lock the passwd file");
			return retval;
		}
		retval = update_pass_special_file(
				 pamh, key_file, spec_pass_file, user, pass_new);
		unlock_pwdf();
		return retval;
	}

	return PAM_SUCCESS;
}

/* end of module definition */
