int main(){ printf("Efective user: %s\n", get_effective_user_name()); printf("Real user: %s\n", get_user_name()); printf("\n"); printf("drop_privs temp\n"); int ret1 = drop_privileges(0); printf("Efective user: %s\n", get_effective_user_name()); printf("Real user: %s\n", get_user_name()); printf("\n"); printf("restore privs\n"); int ret2 = restore_privileges(); printf("Efective user: %s\n", get_effective_user_name()); printf("Real user: %s\n", get_user_name()); printf("\n"); printf("drop_privs definitive\n"); int ret3 = drop_privileges(1); printf("Efective user: %s\n", get_effective_user_name()); printf("Real user: %s\n", get_user_name()); printf("\n"); printf("restore privs\n"); int ret4 = restore_privileges(); printf("Efective user: %s\n", get_effective_user_name()); printf("Real user: %s\n", get_user_name()); printf("\n"); printf("return values: %d, %d, %d, %d\n", ret1, ret2, ret3, ret4); return 0; }
int mqtt3_log_init(struct mqtt3_config *config) { int rc = 0; log_priorities = config->log_type; log_destinations = config->log_dest; if(log_destinations & MQTT3_LOG_SYSLOG){ #ifndef WIN32 openlog("mosquitto", LOG_PID|LOG_CONS, config->log_facility); #else syslog_h = OpenEventLog(NULL, "mosquitto"); #endif } if(log_destinations & MQTT3_LOG_FILE){ if(drop_privileges(config, true)){ return 1; } config->log_fptr = _mosquitto_fopen(config->log_file, "at"); if(!config->log_fptr){ log_destinations = MQTT3_LOG_STDERR; log_priorities = MOSQ_LOG_ERR; _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file); return MOSQ_ERR_INVAL; } restore_privileges(); } return rc; }
/* * Authorize authenticated OTP_ID for login as USERNAME using * AUTHFILE. Return 0 on failures, otherwise success. */ static int authorize_user_token (struct cfg *cfg, const char *username, const char *otp_id, pam_handle_t *pamh) { int retval; if (cfg->auth_file) { /* Administrator had configured the file and specified is name as an argument for this module. */ DBG (("Using system-wide auth_file %s", cfg->auth_file)); retval = check_user_token (cfg, cfg->auth_file, username, otp_id); } else { char *userfile = NULL; struct passwd *p; p = getpwnam (username); if (p == NULL) { DBG (("getpwnam: %s", strerror(errno))); return 0; } /* Getting file from user home directory ..... i.e. ~/.yubico/authorized_yubikeys */ if (! get_user_cfgfile_path (NULL, "authorized_yubikeys", username, &userfile)) { D (("Failed figuring out per-user cfgfile")); return 0; } DBG (("Dropping privileges")); if (drop_privileges(p, pamh) < 0) { D (("could not drop privileges")); return 0; } retval = check_user_token (cfg, userfile, username, otp_id); if (restore_privileges(pamh) < 0) { DBG (("could not restore privileges")); return 0; } free (userfile); } return retval; }
/* expected hook, this is where custom stuff happens */ PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char **argv) { int ret = 0; const char *pUsername = NULL; const char *pAccountId = NULL; const char *pOperation = NULL; const char *pSecretKey = NULL; const char *pAppId = NULL; const char *pOperationId = NULL; const char *pAccounts = NULL; const char *pConfig = NULL; const char *pOtp = NULL; const char *pHost = NULL; const char *pTimeout = NULL; char *pDefaultOption = NULL; char *buffer; int timeout = 2; int default_option = PAM_SUCCESS; int res = PAM_SUCCESS; char *otp = NULL; struct pam_message msg[1],*pmsg[1]; struct pam_response *resp; // setting up conversation call prompting for one-time code pmsg[0] = &msg[0] ; msg[0].msg_style = PAM_PROMPT_ECHO_ON ; msg[0].msg = "One-time code: " ; resp = NULL ; if (pam_get_user(pamh, &pUsername, NULL) != PAM_SUCCESS) { return PAM_AUTH_ERR; } pAccounts = getArg("accounts", argc, argv); if (!pAccounts) { pAccounts = DEFAULT_LATCH_ACCOUNTS_FILE; } pAccountId = getAccountId(pUsername, pAccounts); if (pAccountId == NULL) { return PAM_SUCCESS; } pConfig = getArg("config", argc, argv); if (!pConfig) { pConfig = DEFAULT_LATCH_CONFIG_FILE; } pOperation = getArg("operation", argc, argv); if (!pOperation) { pOperationId = NULL; } else { pOperationId = getConfig(OPERATION_ID_LENGTH, pOperation, pConfig); if (pOperationId == NULL) { send_syslog_alert("PAM", "Latch-auth-pam error: Failed to find operation"); perror("Failed to find operation"); return PAM_SUCCESS; } } pOtp = getArg("otp", argc, argv); if (!pOtp) { pOtp = "no"; } pDefaultOption = (char *)getConfig(DEFAULT_OPTION_MAX_LENGTH, "action", pConfig); if (pDefaultOption == NULL) { pDefaultOption = malloc(4 + 1); memset(pDefaultOption, 0, 4 + 1); strncpy(pDefaultOption, "open", 4); } else if (strcmp(pDefaultOption,"open") != 0 && strcmp(pDefaultOption,"close") != 0){ pDefaultOption = realloc(pDefaultOption, 4 + 1); memset(pDefaultOption, 0, 4 + 1); strncpy(pDefaultOption, "open", 4); } if (strcmp(pDefaultOption,"open") == 0) { default_option = PAM_SUCCESS; } else { default_option = PAM_AUTH_ERR; } free(pDefaultOption); pAppId = getConfig(APP_ID_LENGTH, "app_id", pConfig); pSecretKey = getConfig(SECRET_KEY_LENGTH, "secret_key", pConfig); if(pAppId == NULL || pSecretKey == NULL || strcmp(pAppId, "") == 0 || strcmp(pSecretKey, "") == 0){ send_syslog_alert("PAM", "Latch-auth-pam error: Failed to read \"latch.conf\""); perror("Failed to read \"latch.conf\""); free((char*)pAccountId); free((char*)pOperationId); return PAM_SUCCESS; } pHost = getConfig(MAX_SIZE, "latch_host", pConfig); if(pHost == NULL) { pHost = malloc(LATCH_API_HOST_LENGTH + 1); memset((char*)pHost, 0, LATCH_API_HOST_LENGTH + 1); strncpy((char*)pHost, LATCH_API_HOST, LATCH_API_HOST_LENGTH); } pTimeout = getConfig(TIMEOUT_MAX_LENGTH, "timeout", pConfig); if(pTimeout == NULL || ((timeout = atoi(pTimeout)) < TIMEOUT_MIN) || timeout > TIMEOUT_MAX) { timeout = 2; } free((char*)pTimeout); if (drop_privileges(0)) { send_syslog_alert("PAM", "Latch-auth-pam error: Couldn't drop privileges"); } init(pAppId, pSecretKey); setHost(pHost); setTimeout(timeout); if (pOperationId != NULL) { buffer = operationStatus(pAccountId, pOperationId); } else { buffer = status(pAccountId); } free((char*)pAppId); free((char*)pSecretKey); free((char*)pAccountId); free((char*)pOperationId); free((char*)pHost); if (restore_privileges()) { send_syslog_alert("PAM", "Latch-auth-pam error: Couldn't restore privileges"); } if(buffer == NULL || strcmp(buffer,"") == 0){ free(buffer); return default_option; } if (strstr(buffer, "\"status\":\"off\"") != NULL){ fprintf (stderr, "AUTH-PAM: latch locked\n"); send_syslog_alert("PAM", "Latch-auth-pam warning: Someone tried to access. Latch locked"); res = PAM_AUTH_ERR; }else if (strstr(buffer, "\"status\":\"on\"") != NULL) { if(strncmp(pOtp, "yes", 3) == 0){ char *pch; if((pch = strstr(buffer, "\"two_factor\"")) != NULL){ char code[OTP_LENGTH]; memset(code, 0, OTP_LENGTH); strncpy (code, pch + strlen("\"two_factor\":{\"token\":\""), OTP_LENGTH); otp = get_response(pamh, "One-time password", 1); // comparing user input with known code if(strncmp(code, otp, OTP_LENGTH) != 0 || strlen(otp) != OTP_LENGTH){ send_syslog_alert("PAM", "Latch-auth-pam warning: Someone tried to access. Bad OTP"); res = PAM_AUTH_ERR; } else { res = PAM_SUCCESS; } } }else{ res = PAM_SUCCESS; } } free(buffer); return res; }
static int do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username) { char *userfile = NULL, *tmpfile = NULL; FILE *f = NULL; char buf[CR_RESPONSE_SIZE + 16], response_hex[CR_RESPONSE_SIZE * 2 + 1]; int ret, fd; unsigned int flags = 0; unsigned int response_len = 0; YK_KEY *yk = NULL; CR_STATE state; char *errstr = NULL; struct passwd *p; struct stat st; ret = PAM_AUTH_ERR; flags |= YK_FLAG_MAYBLOCK; if (! init_yubikey(&yk)) { D(("Failed initializing YubiKey")); goto out; } if (! check_firmware_version(yk, false, true)) { D(("YubiKey does not support Challenge-Response (version 2.2 required)")); goto out; } if (! get_user_challenge_file (yk, cfg->chalresp_path, username, &userfile)) { D(("Failed getting user challenge file for user %s", username)); goto out; } DBG(("Loading challenge from file %s", userfile)); p = getpwnam (username); if (p == NULL) { DBG (("getpwnam: %s", strerror(errno))); goto out; } /* Drop privileges before opening user file. */ if (drop_privileges(p, pamh) < 0) { D (("could not drop privileges")); goto out; } fd = open(userfile, O_RDONLY, 0); if (fd < 0) { DBG (("Cannot open file: %s (%s)", userfile, strerror(errno))); goto out; } if (fstat(fd, &st) < 0) { DBG (("Cannot stat file: %s (%s)", userfile, strerror(errno))); close(fd); goto out; } if (!S_ISREG(st.st_mode)) { DBG (("%s is not a regular file", userfile)); close(fd); goto out; } f = fdopen(fd, "r"); if (f == NULL) { DBG (("fdopen: %s", strerror(errno))); close(fd); goto out; } if (! load_chalresp_state(f, &state, cfg->debug)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } f = NULL; if (restore_privileges(pamh) < 0) { DBG (("could not restore privileges")); goto out; } if (! challenge_response(yk, state.slot, state.challenge, state.challenge_len, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Challenge-response FAILED")); goto out; } /* * Check YubiKey response against the expected response */ yubikey_hex_encode(response_hex, buf, response_len); if (memcmp(buf, state.response, response_len) == 0) { ret = PAM_SUCCESS; } else { D(("Unexpected C/R response : %s", response_hex)); goto out; } DBG(("Got the expected response, generating new challenge (%i bytes).", CR_CHALLENGE_SIZE)); errstr = "Error generating new challenge, please check syslog or contact your system administrator"; if (generate_random(state.challenge, sizeof(state.challenge))) { D(("Failed generating new challenge!")); goto out; } errstr = "Error communicating with Yubikey, please check syslog or contact your system administrator"; if (! challenge_response(yk, state.slot, state.challenge, CR_CHALLENGE_SIZE, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Second challenge-response FAILED")); goto out; } /* the yk_* functions leave 'junk' in errno */ errno = 0; /* * Write the challenge and response we will expect the next time to the state file. */ if (response_len > sizeof(state.response)) { D(("Got too long response ??? (%u/%lu)", response_len, (unsigned long) sizeof(state.response))); goto out; } memcpy (state.response, buf, response_len); state.response_len = response_len; /* Drop privileges before creating new challenge file. */ if (drop_privileges(p, pamh) < 0) { D (("could not drop privileges")); goto out; } /* Write out the new file */ tmpfile = malloc(strlen(userfile) + 1 + 4); if (! tmpfile) goto out; strcpy(tmpfile, userfile); strcat(tmpfile, ".tmp"); f = fopen(tmpfile, "w"); if (! f) goto out; errstr = "Error updating Yubikey challenge, please check syslog or contact your system administrator"; if (! write_chalresp_state (f, &state)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } f = NULL; if (rename(tmpfile, userfile) < 0) { goto out; } if (restore_privileges(pamh) < 0) { DBG (("could not restore privileges")); goto out; } DBG(("Challenge-response success!")); errstr = NULL; errno = 0; out: if (yk_errno) { if (yk_errno == YK_EUSBERR) { syslog(LOG_ERR, "USB error: %s", yk_usb_strerror()); D(("USB error: %s", yk_usb_strerror())); } else { syslog(LOG_ERR, "Yubikey core error: %s", yk_strerror(yk_errno)); D(("Yubikey core error: %s", yk_strerror(yk_errno))); } } if (errstr) display_error(pamh, errstr); if (errno) { syslog(LOG_ERR, "Challenge response failed: %s", strerror(errno)); D(("Challenge response failed: %s", strerror(errno))); } if (yk) yk_close_key(yk); yk_release(); if (f) fclose(f); free(userfile); free(tmpfile); return ret; }
void test_drop_privileges() { char *e_user_name_initial = get_effective_user_name(); char *r_user_name_initial = get_user_name(); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name_initial); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name_initial); // drop_privs temp int response1 = drop_privileges(0); char *e_user_name1 = get_effective_user_name(); char *r_user_name1 = get_user_name(); CU_ASSERT_FALSE(response1); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name1); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name1); CU_ASSERT_STRING_EQUAL(r_user_name1, e_user_name1); // drop_privs temp again int response2 = drop_privileges(0); char *e_user_name2 = get_effective_user_name(); char *r_user_name2 = get_user_name(); CU_ASSERT_FALSE(response2); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name2); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name2); CU_ASSERT_STRING_EQUAL(r_user_name2, e_user_name2); // restore privs int response3 = restore_privileges(); char *e_user_name3 = get_effective_user_name(); char *r_user_name3 = get_user_name(); CU_ASSERT_FALSE(response3); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name3); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name3); CU_ASSERT_STRING_EQUAL(e_user_name_initial, e_user_name3); // drop_privs definitely int response4 = drop_privileges(1); char *e_user_name4 = get_effective_user_name(); char *r_user_name4 = get_user_name(); CU_ASSERT_FALSE(response4); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name4); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name4); CU_ASSERT_STRING_EQUAL(r_user_name4, e_user_name4); // restore privs int response5 = restore_privileges(); char *e_user_name5 = get_effective_user_name(); char *r_user_name5 = get_user_name(); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name5); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name5); CU_ASSERT_STRING_EQUAL(r_user_name5, e_user_name5); // drop_privs temp (being dropped definitely) int response6 = drop_privileges(0); char *e_user_name6 = get_effective_user_name(); char *r_user_name6 = get_user_name(); CU_ASSERT_FALSE(response6); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name6); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name6); CU_ASSERT_STRING_EQUAL(r_user_name6, e_user_name6); // drop_privs definitely again int response7 = drop_privileges(1); char *e_user_name7 = get_effective_user_name(); char *r_user_name7 = get_user_name(); CU_ASSERT_FALSE(response7); CU_ASSERT_PTR_NOT_NULL_FATAL(e_user_name7); CU_ASSERT_PTR_NOT_NULL_FATAL(r_user_name7); CU_ASSERT_STRING_EQUAL(r_user_name7, e_user_name7); }