/*
// 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;
	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 */
