PAM_EXTERN int pam_sm_authenticate ( pam_handle_t *pamh, int flags, int argc, const char *argv[] ) { int retval; const char *user, *prompt; char *data,*data2,*flag; char * pwdt,*pwds; retval = pam_get_user ( pamh, &user, NULL ); if (retval != PAM_SUCCESS) return retval; D(("Got user: %s", user)); D(("cenas")); pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &data,"attempt"); if(data == NULL) return PAM_AUTH_ERR; Base64Decode(data,&pwdt); D(("Attempted Password: %s \n", pwdt)); pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &data2,"storedpassword"); Base64Decode(data2,&pwds); if(strlen(data2) == 0) return PAM_AUTH_ERR; D(("Stored Password: %s \n", pwds)); if(strcmp(pwdt,pwds) == 0){ D(("PTEID CC authentication: success!")); return PAM_SUCCESS; } return PAM_AUTH_ERR; }
int pam_get_authtok(pam_handle_t *pamh, int item, const char **authtok, const char *prompt) { int rc; char *passwd = NULL, *retype_passwd = NULL; const void *oldauthtok; char retype_prompt[80]; /* first try to see if the value is already on the stack */ *authtok = NULL; rc = pam_get_item(pamh, item, (PAM_ITEM_CONST void **)authtok); if ((rc == PAM_SUCCESS) && (*authtok != NULL)) return PAM_SUCCESS; /* check what to prompt for and provide default prompt */ *retype_prompt = '\0'; if (item == PAM_OLDAUTHTOK) prompt = (prompt != NULL) ? prompt : "Old Password: "******"New Password: "******"Retype %s", prompt); retype_prompt[sizeof(retype_prompt) - 1] = '\0'; } else prompt = (prompt != NULL) ? prompt : "Password: "******"%s", prompt); if (rc != PAM_SUCCESS) return rc; /* if a second prompt should be presented, do it */ if (*retype_prompt) { rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &retype_passwd, "%s", retype_prompt); /* check passwords */ if ((rc == PAM_SUCCESS) && (strcmp(retype_passwd, passwd) != 0)) rc = PAM_AUTHTOK_RECOVERY_ERR; } /* store the password if everything went ok */ if (rc == PAM_SUCCESS) rc = pam_set_item(pamh, item, passwd); /* clear and free any password information */ memset(passwd, 0, strlen(passwd)); free(passwd); if (retype_passwd != NULL) { memset(retype_passwd, 0, strlen(retype_passwd)); free(retype_passwd); } if (rc != PAM_SUCCESS) return rc; /* return token from the stack */ return pam_get_item(pamh, item, (PAM_ITEM_CONST void **)authtok); }
int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { const void *promptp; char *resp; int r; ENTER(); if (pamh == NULL || user == NULL) RETURNC(PAM_SYSTEM_ERR); r = pam_get_item(pamh, PAM_USER, (const void **)user); if (r == PAM_SUCCESS && *user != NULL) RETURNC(PAM_SUCCESS); if (prompt == NULL) { r = pam_get_item(pamh, PAM_USER_PROMPT, &promptp); if (r != PAM_SUCCESS || promptp == NULL) prompt = user_prompt; else prompt = promptp; } r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt); if (r != PAM_SUCCESS) RETURNC(r); r = pam_set_item(pamh, PAM_USER, resp); FREE(resp); if (r != PAM_SUCCESS) RETURNC(r); r = pam_get_item(pamh, PAM_USER, (const void **)user); RETURNC(r); }
inline const char * otp_get_from_user(pam_handle_t *pamh) { char *resp = NULL; pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, PROMPT); return resp; }
/* * Conversation function to obtain the user's password */ static int obtain_authtok(pam_handle_t *pamh) { char *resp; const void *item; int retval; retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, _("Password: ")); if (retval != PAM_SUCCESS) return retval; if (resp == NULL) return PAM_CONV_ERR; /* set the auth token */ retval = pam_set_item(pamh, PAM_AUTHTOK, resp); /* clean it up */ _pam_overwrite(resp); _pam_drop(resp); if ( (retval != PAM_SUCCESS) || (retval = pam_get_item(pamh, PAM_AUTHTOK, &item)) != PAM_SUCCESS ) { return retval; } return retval; }
int pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc, const char **argv) { pam_syslog(pamh, LOG_DEBUG,"LINE: %d, FUNC: %s, FILE: %s, %s", __LINE__, __func__, __FILE__, "acct_mgmt test!\n"); pam_prompt(pamh, PAM_ERROR_MSG, NULL, "LINE: %d, FUNC: %s, FILE: %s, %s", __LINE__, __func__, __FILE__, "acct_mgmt test!\n"); return PAM_SUCCESS; }
static void test_pam_prompt(void **state) { struct pwrap_test_ctx *test_ctx; int rv; char *response; int resp_array[2]; test_ctx = (struct pwrap_test_ctx *) *state; memset(resp_array, 0, sizeof(resp_array)); test_ctx->conv.conv = pwrap_echo_conv; test_ctx->conv.appdata_ptr = resp_array; rv = pam_start("matrix", "trinity", &test_ctx->conv, &test_ctx->ph); assert_int_equal(rv, PAM_SUCCESS); rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_OFF, &response, "no echo"); assert_int_equal(rv, PAM_SUCCESS); assert_string_equal(response, "echo off: no echo"); free(response); rv = vprompt_test_fn(test_ctx->ph, PAM_PROMPT_ECHO_OFF, &response, "no echo"); assert_int_equal(rv, PAM_SUCCESS); assert_string_equal(response, "echo off: no echo"); free(response); rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_ON, &response, "echo"); assert_int_equal(rv, PAM_SUCCESS); assert_string_equal(response, "echo on: echo"); free(response); rv = vprompt_test_fn(test_ctx->ph, PAM_PROMPT_ECHO_ON, &response, "echo"); assert_int_equal(rv, PAM_SUCCESS); assert_string_equal(response, "echo on: echo"); free(response); assert_int_equal(resp_array[0], 0); pam_info(test_ctx->ph, "info"); assert_int_equal(resp_array[0], 1); assert_int_equal(resp_array[1], 0); pam_error(test_ctx->ph, "error"); assert_int_equal(resp_array[1], 1); }
int _make_remark(pam_handle_t * pamh, unsigned int ctrl, int type, const char *text) { int retval = PAM_SUCCESS; if (off(UNIX__QUIET, ctrl)) { retval = pam_prompt(pamh, type, NULL, "%s", text); } return retval; }
/* * This function sends a message to the user and gets the response. The caller * is responsible for freeing the responses. */ static int query_response (pam_handle_t *pamh, const char *text, const char *def, char **response, int debug) { int rc; if (def) rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def); else rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s ", text); if (*response == NULL) { rc = PAM_CONV_ERR; } if (rc != PAM_SUCCESS) { pam_syslog(pamh, LOG_WARNING, "No response to query: %s", text); } else if (debug) pam_syslog(pamh, LOG_NOTICE, "%s %s", text, *response); return rc; }
static char * __duo_prompt(void *arg, const char *prompt, char *buf, size_t bufsz) { char *p = NULL; if (pam_prompt((pam_handle_t *)arg, PAM_PROMPT_ECHO_ON, &p, "%s", prompt) != PAM_SUCCESS || p == NULL) { return (NULL); } strlcpy(buf, p, bufsz); free(p); return (buf); }
int _whawty_get_password(whawty_ctx_t* ctx) { if(ctx->flags_ & WHAWTY_CONF_USE_FIRST_PASS || ctx->flags_ & WHAWTY_CONF_TRY_FIRST_PASS) { // fetch password from stack char* pwd; int ret = pam_get_item(ctx->pamh_, PAM_AUTHTOK, (const void**)(&pwd)); if(ret != PAM_SUCCESS) { _whawty_logf(ctx, LOG_ERR, "pam_get_item() returned an error reading the password [%s]", pam_strerror(ctx->pamh_, ret)); return ret; } if(pwd != NULL) { ctx->password_ = strdup(pwd); if(ctx->password_ == NULL) return PAM_BUF_ERR; _whawty_logf(ctx, LOG_DEBUG, "successfully fetched password [from stack]"); return PAM_SUCCESS; } if(ctx->flags_ & WHAWTY_CONF_USE_FIRST_PASS) { _whawty_logf(ctx, LOG_ERR, "no password on stack and use_first_pass is set"); return PAM_AUTHTOK_RECOVERY_ERR; } } // fetch password using the conversation function int ret = pam_prompt(ctx->pamh_, PAM_PROMPT_ECHO_OFF, &(ctx->password_), "Password: "******"conversation function is not ready yet"); return PAM_INCOMPLETE; } _whawty_logf(ctx, LOG_ERR, "pam_prompt() returned an error reading the password [%s]", pam_strerror(ctx->pamh_, ret)); return ret; } if(ctx->password_ == NULL) { _whawty_logf(ctx, LOG_ERR, "conversation function returned no password"); return PAM_AUTHTOK_RECOVERY_ERR; } _whawty_logf(ctx, LOG_DEBUG, "successfully fetched password [from conversation function]"); if(!(ctx->flags_ & WHAWTY_CONF_NOT_SET_PASS)) { // set PAM_AUTHTOK item to ctx->password_ return pam_set_item(ctx->pamh_, PAM_AUTHTOK, ctx->password_); } return PAM_SUCCESS; }
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { char *login_token_name; ERR("Warning: Function pam_sm_chauthtok() is not implemented in this module"); pam_syslog(pamh, LOG_WARNING, "Function pam_sm_chauthtok() is not implemented in this module"); login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME"); if (login_token_name && (flags & PAM_PRELIM_CHECK)) { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Cannot change the password on your smart card.")); } return PAM_SERVICE_ERR; }
int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { char prompt_buf[1024]; size_t prompt_size; const void *promptp; char *resp; int r; ENTER(); if (pamh == NULL || user == NULL) RETURNC(PAM_SYSTEM_ERR); r = pam_get_item(pamh, PAM_USER, (const void **)user); if (r == PAM_SUCCESS && *user != NULL) RETURNC(PAM_SUCCESS); /* pam policy overrides the module's choice */ if ((promptp = openpam_get_option(pamh, "user_prompt")) != NULL) prompt = promptp; /* no prompt provided, see if there is one tucked away somewhere */ if (prompt == NULL) if (pam_get_item(pamh, PAM_USER_PROMPT, &promptp) && promptp != NULL) prompt = promptp; /* fall back to hardcoded default */ if (prompt == NULL) prompt = user_prompt; /* expand */ prompt_size = sizeof prompt_buf; r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt); if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf) prompt = prompt_buf; r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt); if (r != PAM_SUCCESS) RETURNC(r); r = pam_set_item(pamh, PAM_USER, resp); FREE(resp); if (r != PAM_SUCCESS) RETURNC(r); r = pam_get_item(pamh, PAM_USER, (const void **)user); RETURNC(r); }
static char *request_random(pam_handle_t *pamh, int echocode, const char *prompt) { //const struct pam_message msg = { .msg_style = echocode, // .msg = prompt }; //const struct pam_message *msgs = &msg; //struct pam_response *resp = NULL; char *resp; //int retval = converse(pamh, 1, &msgs, &resp); (void) pam_prompt(pamh, echocode, &resp, "%s", prompt); //int retval = misc_conv(1, &msgs, &resp, NULL); if( resp == NULL ) { static char result = 0; resp = &result; } return resp; }
int get_password(pam_handle_t* pamh, pam_url_opts* opts) { char* p = NULL; const char *prompt; int prompt_len = 0; if(config_lookup_string(&config, "pam_url.settings.prompt", &prompt) == CONFIG_FALSE) prompt = DEF_PROMPT; pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &p, "%s", prompt); if( NULL != p && strlen(p) > 0) { opts->passwd = p; return PAM_SUCCESS; } else { return PAM_AUTH_ERR; } }
/***************************************************************************** Func Name: pam_local_obtain_authtok Date Created: 2009/3/5 Author: chendong Description: 获取用户密码 Input: pam_handle_t *pamh PAM HANDLE Output: Return: PAM错误码 Caution: ----------------------------------------------------------------------------- Modification History DATE NAME DESCRIPTION ----------------------------------------------------------------------------- ******************************************************************************/ static int pam_local_obtain_authtok(pam_handle_t *pamh) { char *resp; int retval; retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, "Password: "); if (retval != PAM_SUCCESS) { return retval; } if (resp == NULL) { return PAM_CONV_ERR; } /* set the auth token */ retval = pam_set_item(pamh, PAM_AUTHTOK, resp); return retval; }
int pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int retval, anon=0, ctrl; const char *user; const char *users = NULL; /* * this module checks if the user name is ftp or annonymous. If * this is the case, it can set the PAM_RUSER to the entered email * address and SUCCEEDS, otherwise it FAILS. */ ctrl = _pam_parse(pamh, argc, argv, &users); retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS || user == NULL) { pam_syslog(pamh, LOG_ERR, "no user specified"); return PAM_USER_UNKNOWN; } if (!(ctrl & PAM_NO_ANON)) { anon = lookup(user, users, &user); } if (anon) { retval = pam_set_item(pamh, PAM_USER, (const void *)user); if (retval != PAM_SUCCESS || user == NULL) { pam_syslog(pamh, LOG_ERR, "user resetting failed"); return PAM_USER_UNKNOWN; } } /* * OK. we require an email address for user or the user's password. * - build conversation and get their input. */ { char *resp = NULL; const char *token; if (!anon) retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, PLEASE_ENTER_PASSWORD, user); else retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, GUEST_LOGIN_PROMPT); if (retval != PAM_SUCCESS) { _pam_overwrite (resp); _pam_drop (resp); return ((retval == PAM_CONV_AGAIN) ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL); } if (anon) { /* XXX: Some effort should be made to verify this email address! */ if (!(ctrl & PAM_IGNORE_EMAIL)) { char *sptr = NULL; token = strtok_r(resp, "@", &sptr); retval = pam_set_item(pamh, PAM_RUSER, token); if ((token) && (retval == PAM_SUCCESS)) { token = strtok_r(NULL, "@", &sptr); retval = pam_set_item(pamh, PAM_RHOST, token); } } /* we are happy to grant annonymous access to the user */ retval = PAM_SUCCESS; } else { /* * we have a password so set AUTHTOK */ pam_set_item(pamh, PAM_AUTHTOK, resp); /* * this module failed, but the next one might succeed with * this password. */ retval = PAM_AUTH_ERR; } /* clean up */ _pam_overwrite(resp); _pam_drop(resp); /* success or failure */ return retval; } }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int i, rv; const char *user = NULL; char *password; unsigned int slot_num = 0; int is_a_screen_saver = 0; struct configuration_st *configuration; int pkcs11_pam_fail = PAM_AUTHINFO_UNAVAIL; pkcs11_handle_t *ph; cert_object_t *chosen_cert = NULL; cert_object_t **cert_list; int ncert; unsigned char random_value[128]; unsigned char *signature; unsigned long signature_length; /* enough space to hold an issuer DN */ char env_temp[256] = ""; char **issuer, **serial; const char *login_token_name = NULL; pam_prompt(pamh, PAM_TEXT_INFO , NULL, _("Smartcard authentication starts")); /* first of all check whether debugging should be enabled */ for (i = 0; i < argc; i++) if (strcmp("debug", argv[i]) == 0) { set_debug_level(1); } /* call configure routines */ configuration = pk_configure(argc,argv); if (!configuration ) { ERR("Error setting configuration parameters"); return PAM_AUTHINFO_UNAVAIL; } /* Either slot_description or slot_num, but not both, needs to be used */ if ((configuration->slot_description != NULL && configuration->slot_num != -1) || (configuration->slot_description == NULL && configuration->slot_num == -1)) { ERR("Error setting configuration parameters"); return PAM_AUTHINFO_UNAVAIL; } /* fail if we are using a remote server * local login: DISPLAY=:0 * XDMCP login: DISPLAY=host:0 */ { char *display = getenv("DISPLAY"); if (display) { if (strncmp(display, "localhost:", 10) != 0 && (display[0] != ':') && (display[0] != '\0')) { ERR1("Remote login (from %s) is not (yet) supported", display); pam_syslog(pamh, LOG_ERR, "Remote login (from %s) is not (yet) supported", display); return PAM_AUTHINFO_UNAVAIL; } } } #ifdef ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, "/usr/share/locale"); textdomain(PACKAGE); #endif /* init openssl */ rv = crypto_init(&configuration->policy); if (rv != 0) { ERR("Failed to initialize crypto"); if (!configuration->quiet) pam_syslog(pamh,LOG_ERR, "Failed to initialize crypto"); return PAM_AUTHINFO_UNAVAIL; } /* * card_only means: * 1) always get the userid from the certificate. * 2) don't prompt for the user name if the card is present. * 3) if the token is present, then we must use the cardAuth mechanism. * * wait_for_card means: * 1) nothing if card_only isn't set * 2) if logged in, block in pam conversation until the token used for login * is inserted * 3) if not logged in, block until a token that could be used for logging in * is inserted * right now, logged in means PKC11_LOGIN_TOKEN_NAME is set, * but we could something else later (like set some per-user state in * a pam session module keyed off uid) */ if (configuration->card_only) { char *service; if (configuration->screen_savers) { DBG("Is it a screen saver?"); pam_get_item(pamh, PAM_SERVICE, &service); for (i=0; configuration->screen_savers[i]; i++) { if (strcmp(configuration->screen_savers[i], service) == 0) { is_a_screen_saver = 1; break; } } } pkcs11_pam_fail = PAM_CRED_INSUFFICIENT; /* look to see if username is already set */ pam_get_item(pamh, PAM_USER, &user); if (user) { DBG1("explicit username = [%s]", user); } } else { rv = pam_get_item(pamh, PAM_USER, &user); if (rv != PAM_SUCCESS || user == NULL || user[0] == '\0') { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Please insert your %s or enter your username."), _(configuration->token_type)); /* get user name */ rv = pam_get_user(pamh, &user, NULL); if (rv != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_get_user() failed %s", pam_strerror(pamh, rv)); return PAM_USER_UNKNOWN; } } DBG1("username = [%s]", user); } login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME"); /* if we are using a screen saver, and we didn't log in using the smart card * drop to the next pam module. */ if (is_a_screen_saver && !login_token_name) { return PAM_IGNORE; } /* load pkcs #11 module */ DBG("loading pkcs #11 module..."); rv = load_pkcs11_module(configuration->pkcs11_modulepath, &ph); if (rv != 0) { ERR2("load_pkcs11_module() failed loading %s: %s", configuration->pkcs11_modulepath, get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "load_pkcs11_module() failed loading %s: %s", configuration->pkcs11_modulepath, get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2302: PKCS#11 module failed loading")); sleep(configuration->err_display_time); } return PAM_AUTHINFO_UNAVAIL; } /* initialise pkcs #11 module */ DBG("initialising pkcs #11 module..."); rv = init_pkcs11_module(ph,configuration->support_threads); if (rv != 0) { release_pkcs11_module(ph); ERR1("init_pkcs11_module() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "init_pkcs11_module() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2304: PKCS#11 module could not be initialized")); sleep(configuration->err_display_time); } return PAM_AUTHINFO_UNAVAIL; } /* open pkcs #11 session */ if (configuration->slot_description != NULL) { rv = find_slot_by_slotlabel_and_tokenlabel(ph, configuration->slot_description, login_token_name, &slot_num); } else if (configuration->slot_num != -1) { rv = find_slot_by_number_and_label(ph, configuration->slot_num, login_token_name, &slot_num); } if (rv != 0) { ERR("no suitable token available"); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "no suitable token available"); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2306: No suitable token available")); sleep(configuration->err_display_time); } if (!configuration->card_only) { release_pkcs11_module(ph); return PAM_AUTHINFO_UNAVAIL; } /* we must have a smart card, either because we've configured it as such, * or because we used one to log in */ if (login_token_name || configuration->wait_for_card) { if (login_token_name) { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Please insert your smart card called \"%.32s\"."), login_token_name); } else { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Please insert your smart card.")); } if (configuration->slot_description != NULL) { rv = wait_for_token_by_slotlabel(ph, configuration->slot_description, login_token_name, &slot_num); } else if (configuration->slot_num != -1) { rv = wait_for_token(ph, configuration->slot_num, login_token_name, &slot_num); } if (rv != 0) { release_pkcs11_module(ph); return pkcs11_pam_fail; } } else if (user) { if (!configuration->quiet) { pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2308: No smartcard found")); sleep(configuration->err_display_time); } /* we have a user and no smart card, go to the next pam module */ release_pkcs11_module(ph); return PAM_AUTHINFO_UNAVAIL; } else { /* we haven't prompted for the user yet, get the user and see if * the smart card has been inserted in the mean time */ pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Please insert your %s or enter your username."), _(configuration->token_type)); rv = pam_get_user(pamh, &user, NULL); /* check one last time for the smart card before bouncing to the next * module */ if (configuration->slot_description != NULL) { rv = find_slot_by_slotlabel(ph, configuration->slot_description, &slot_num); } else if (configuration->slot_num != -1) { rv = find_slot_by_number(ph, configuration->slot_num, &slot_num); } if (rv != 0) { /* user gave us a user id and no smart card go to next module */ if (!configuration->quiet) { pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2310: No smartcard found")); sleep(configuration->err_display_time); } release_pkcs11_module(ph); return PAM_AUTHINFO_UNAVAIL; } } } else { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("%s found."), _(configuration->token_type)); } rv = open_pkcs11_session(ph, slot_num); if (rv != 0) { ERR1("open_pkcs11_session() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "open_pkcs11_session() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2312: open PKCS#11 session failed")); sleep(configuration->err_display_time); } release_pkcs11_module(ph); return pkcs11_pam_fail; } rv = get_slot_login_required(ph); if (rv == -1) { ERR1("get_slot_login_required() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "get_slot_login_required() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2314: Slot login failed")); sleep(configuration->err_display_time); } release_pkcs11_module(ph); return pkcs11_pam_fail; } else if (rv) { /* get password */ pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Welcome %.32s!"), get_slot_tokenlabel(ph)); /* no CKF_PROTECTED_AUTHENTICATION_PATH */ rv = get_slot_protected_authentication_path(ph); if ((-1 == rv) || (0 == rv)) { char password_prompt[128]; snprintf(password_prompt, sizeof(password_prompt), _("%s PIN: "), _(configuration->token_type)); if (configuration->use_first_pass) { rv = pam_get_pwd(pamh, &password, NULL, PAM_AUTHTOK, 0); } else if (configuration->try_first_pass) { rv = pam_get_pwd(pamh, &password, password_prompt, PAM_AUTHTOK, PAM_AUTHTOK); } else { rv = pam_get_pwd(pamh, &password, password_prompt, 0, PAM_AUTHTOK); } if (rv != PAM_SUCCESS) { if (!configuration->quiet) { pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2316: password could not be read")); sleep(configuration->err_display_time); } release_pkcs11_module(ph); pam_syslog(pamh, LOG_ERR, "pam_get_pwd() failed: %s", pam_strerror(pamh, rv)); return pkcs11_pam_fail; } #ifdef DEBUG_SHOW_PASSWORD DBG1("password = [%s]", password); #endif /* check password length */ if (!configuration->nullok && strlen(password) == 0) { release_pkcs11_module(ph); memset(password, 0, strlen(password)); free(password); pam_syslog(pamh, LOG_ERR, "password length is zero but the 'nullok' argument was not defined."); if (!configuration->quiet) { pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2318: Empty smartcard PIN not allowed.")); sleep(configuration->err_display_time); } return PAM_AUTH_ERR; } } else { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Enter your %s PIN on the pinpad"), _(configuration->token_type)); /* use pin pad */ password = NULL; } /* call pkcs#11 login to ensure that the user is the real owner of the card * we need to do thise before get_certificate_list because some tokens * can not read their certificates until the token is authenticated */ rv = pkcs11_login(ph, password); /* erase and free in-memory password data asap */ if (password) { memset(password, 0, strlen(password)); free(password); } if (rv != 0) { ERR1("open_pkcs11_login() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "open_pkcs11_login() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2320: Wrong smartcard PIN")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } } cert_list = get_certificate_list(ph, &ncert); if (rv<0) { ERR1("get_certificate_list() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "get_certificate_list() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2322: No certificate found")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } /* load mapper modules */ load_mappers(configuration->ctx); /* find a valid and matching certificates */ for (i = 0; i < ncert; i++) { X509 *x509 = (X509 *)get_X509_certificate(cert_list[i]); if (!x509 ) continue; /* sanity check */ DBG1("verifying the certificate #%d", i + 1); if (!configuration->quiet) { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("verifying certificate")); } /* verify certificate (date, signature, CRL, ...) */ rv = verify_certificate(x509,&configuration->policy); if (rv < 0) { ERR1("verify_certificate() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "verify_certificate() failed: %s", get_error()); switch (rv) { case -2: // X509_V_ERR_CERT_HAS_EXPIRED: pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2324: Certificate has expired")); break; case -3: // X509_V_ERR_CERT_NOT_YET_VALID: pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2326: Certificate not yet valid")); break; case -4: // X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2328: Certificate signature invalid")); break; default: pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2330: Certificate invalid")); break; } sleep(configuration->err_display_time); } continue; /* try next certificate */ } else if (rv != 1) { ERR1("verify_certificate() failed: %s", get_error()); continue; /* try next certificate */ } /* CA and CRL verified, now check/find user */ if ( is_spaced_str(user) ) { /* if provided user is null or empty extract and set user name from certificate */ DBG("Empty login: try to deduce from certificate"); user=find_user(x509); if (!user) { ERR2("find_user() failed: %s on cert #%d", get_error(),i+1); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "find_user() failed: %s on cert #%d",get_error(),i+1); continue; /* try on next certificate */ } else { DBG1("certificate is valid and matches user %s",user); /* try to set up PAM user entry with evaluated value */ rv = pam_set_item(pamh, PAM_USER,(const void *)user); if (rv != PAM_SUCCESS) { ERR1("pam_set_item() failed %s", pam_strerror(pamh, rv)); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "pam_set_item() failed %s", pam_strerror(pamh, rv)); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2332: setting PAM userentry failed")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } chosen_cert = cert_list[i]; break; /* end loop, as find user success */ } } else { /* User provided: check whether the certificate matches the user */ rv = match_user(x509, user); if (rv < 0) { /* match error; abort and return */ ERR1("match_user() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "match_user() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2334: No matching user")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } else if (rv == 0) { /* match didn't success */ DBG("certificate is valid but does not match the user"); continue; /* try next certificate */ } else { /* match success */ DBG("certificate is valid and matches the user"); chosen_cert = cert_list[i]; break; } } /* if is_spaced string */ } /* for (i=0; i<ncerts; i++) */ /* now myCert points to our found certificate or null if no user found */ if (!chosen_cert) { ERR("no valid certificate which meets all requirements found"); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "no valid certificate which meets all requirements found"); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2336: No matching certificate found")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } /* if signature check is enforced, generate random data, sign and verify */ if (configuration->policy.signature_policy) { pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Checking signature")); #ifdef notdef rv = get_private_key(ph); if (rv != 0) { ERR1("get_private_key() failed: %s", get_error()); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "get_private_key() failed: %s", get_error()); goto auth_failed_nopw; } #endif /* read random value */ rv = get_random_value(random_value, sizeof(random_value)); if (rv != 0) { ERR1("get_random_value() failed: %s", get_error()); if (!configuration->quiet){ pam_syslog(pamh, LOG_ERR, "get_random_value() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2338: Getting random value failed")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } /* sign random value */ signature = NULL; rv = sign_value(ph, chosen_cert, random_value, sizeof(random_value), &signature, &signature_length); if (rv != 0) { ERR1("sign_value() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "sign_value() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2340: Signing failed")); sleep(configuration->err_display_time); } goto auth_failed_nopw; } /* verify the signature */ DBG("verifying signature..."); rv = verify_signature((X509 *)get_X509_certificate(chosen_cert), random_value, sizeof(random_value), signature, signature_length); if (signature != NULL) { free(signature); } if (rv != 0) { close_pkcs11_session(ph); release_pkcs11_module(ph); ERR1("verify_signature() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "verify_signature() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2342: Verifying signature failed")); sleep(configuration->err_display_time); } return PAM_AUTH_ERR; } } else { DBG("Skipping signature check"); } /* * fill in the environment variables. */ snprintf(env_temp, sizeof(env_temp) - 1, "PKCS11_LOGIN_TOKEN_NAME=%.*s", (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_TOKEN_NAME=")), get_slot_tokenlabel(ph)); rv = pam_putenv(pamh, env_temp); if (rv != PAM_SUCCESS) { ERR1("could not put token name in environment: %s", pam_strerror(pamh, rv)); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "could not put token name in environment: %s", pam_strerror(pamh, rv)); } issuer = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_ISSUER, ALGORITHM_NULL); if (issuer) { snprintf(env_temp, sizeof(env_temp) - 1, "PKCS11_LOGIN_CERT_ISSUER=%.*s", (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_ISSUER=")), issuer[0]); rv = pam_putenv(pamh, env_temp); } else { ERR("couldn't get certificate issuer."); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "couldn't get certificate issuer."); } if (rv != PAM_SUCCESS) { ERR1("could not put cert issuer in environment: %s", pam_strerror(pamh, rv)); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "could not put cert issuer in environment: %s", pam_strerror(pamh, rv)); } serial = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_SERIAL, ALGORITHM_NULL); if (serial) { snprintf(env_temp, sizeof(env_temp) - 1, "PKCS11_LOGIN_CERT_SERIAL=%.*s", (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_SERIAL=")), serial[0]); rv = pam_putenv(pamh, env_temp); } else { ERR("couldn't get certificate serial number."); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "couldn't get certificate serial number."); } if (rv != PAM_SUCCESS) { ERR1("could not put cert serial in environment: %s", pam_strerror(pamh, rv)); if (!configuration->quiet) pam_syslog(pamh, LOG_ERR, "could not put cert serial in environment: %s", pam_strerror(pamh, rv)); } /* unload mapper modules */ unload_mappers(); /* close pkcs #11 session */ rv = close_pkcs11_session(ph); if (rv != 0) { release_pkcs11_module(ph); ERR1("close_pkcs11_session() failed: %s", get_error()); if (!configuration->quiet) { pam_syslog(pamh, LOG_ERR, "close_pkcs11_module() failed: %s", get_error()); pam_prompt(pamh, PAM_ERROR_MSG , NULL, ("Error 2344: Closing PKCS#11 session failed")); sleep(configuration->err_display_time); } return pkcs11_pam_fail; } /* release pkcs #11 module */ DBG("releasing pkcs #11 module..."); release_pkcs11_module(ph); DBG("authentication succeeded"); return PAM_SUCCESS; /* quick and dirty fail exit point */ memset(password, 0, strlen(password)); free(password); /* erase and free in-memory password data */ auth_failed_nopw: unload_mappers(); close_pkcs11_session(ph); release_pkcs11_module(ph); return pkcs11_pam_fail; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { struct options options; int retval; const char *user; char *principal; char *instance; const char *password; char localhost[MAXHOSTNAMELEN + 1]; struct passwd *pwd; pam_std_option(&options, NULL, argc, argv); PAM_LOG("Options processed"); retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS) PAM_RETURN(retval); PAM_LOG("Got user: %s", user); retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, &options); if (retval != PAM_SUCCESS) PAM_RETURN(retval); PAM_LOG("Got password"); if (gethostname(localhost, sizeof localhost - 1) == -1) PAM_RETURN(PAM_SYSTEM_ERR); PAM_LOG("Got localhost: %s", localhost); principal = strdup(user); if (principal == NULL) PAM_RETURN(PAM_BUF_ERR); instance = strchr(principal, '.'); if (instance != NULL) *instance++ = '\0'; else instance = ""; PAM_LOG("Got principal.instance: %s.%s", principal, instance); retval = PAM_AUTH_ERR; pwd = getpwnam(user); if (pwd != NULL) { if (klogin(pwd, instance, localhost, (char *)password) == 0) { if (!(flags & PAM_SILENT) && notickets && !noticketsdontcomplain) pam_prompt(pamh, PAM_ERROR_MSG, "Warning: no Kerberos tickets issued", NULL); /* * XXX - I think the ticket file isn't supposed to * be created until pam_sm_setcred() is called. */ if (krbtkfile_env != NULL) setenv("KRBTKFILE", krbtkfile_env, 1); retval = PAM_SUCCESS; } PAM_LOG("Done klogin()"); } /* * The PAM infrastructure will obliterate the cleartext * password before returning to the application. */ free(principal); if (retval != PAM_SUCCESS) PAM_VERBOSE_ERROR("Kerberos IV refuses you"); PAM_RETURN(retval); }
int pam_get_authtok(pam_handle_t *pamh, int item, const char **authtok, const char *prompt) { char prompt_buf[1024]; size_t prompt_size; const void *oldauthtok, *prevauthtok, *promptp; const char *prompt_option, *default_prompt; const void *lhost, *rhost; char *resp, *resp2; int pitem, r, style, twice; ENTER(); if (pamh == NULL || authtok == NULL) RETURNC(PAM_SYSTEM_ERR); *authtok = NULL; twice = 0; switch (item) { case PAM_AUTHTOK: pitem = PAM_AUTHTOK_PROMPT; prompt_option = "authtok_prompt"; default_prompt = authtok_prompt; r = pam_get_item(pamh, PAM_RHOST, &rhost); if (r == PAM_SUCCESS && rhost != NULL) { r = pam_get_item(pamh, PAM_HOST, &lhost); if (r == PAM_SUCCESS && lhost != NULL) { if (strcmp(rhost, lhost) != 0) default_prompt = authtok_prompt_remote; } } r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok); if (r == PAM_SUCCESS && oldauthtok != NULL) { default_prompt = newauthtok_prompt; twice = 1; } break; case PAM_OLDAUTHTOK: pitem = PAM_OLDAUTHTOK_PROMPT; prompt_option = "oldauthtok_prompt"; default_prompt = oldauthtok_prompt; twice = 0; break; default: RETURNC(PAM_SYMBOL_ERR); } if (openpam_get_option(pamh, "try_first_pass") || openpam_get_option(pamh, "use_first_pass")) { r = pam_get_item(pamh, item, &prevauthtok); if (r == PAM_SUCCESS && prevauthtok != NULL) { *authtok = prevauthtok; RETURNC(PAM_SUCCESS); } else if (openpam_get_option(pamh, "use_first_pass")) { RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r); } } /* pam policy overrides the module's choice */ if ((promptp = openpam_get_option(pamh, prompt_option)) != NULL) prompt = promptp; /* no prompt provided, see if there is one tucked away somewhere */ if (prompt == NULL) if (pam_get_item(pamh, pitem, &promptp) && promptp != NULL) prompt = promptp; /* fall back to hardcoded default */ if (prompt == NULL) prompt = default_prompt; /* expand */ prompt_size = sizeof prompt_buf; r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt); if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf) prompt = prompt_buf; style = openpam_get_option(pamh, "echo_pass") ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; r = pam_prompt(pamh, style, &resp, "%s", prompt); if (r != PAM_SUCCESS) RETURNC(r); if (twice) { r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt); if (r != PAM_SUCCESS) { strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); RETURNC(r); } if (strcmp(resp, resp2) != 0) { strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); } strlset(resp2, 0, PAM_MAX_RESP_SIZE); FREE(resp2); } if (resp == NULL) RETURNC(PAM_TRY_AGAIN); r = pam_set_item(pamh, item, resp); strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); if (r != PAM_SUCCESS) RETURNC(r); r = pam_get_item(pamh, item, (const void **)authtok); RETURNC(r); }
PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) { DBusGConnection *bus; DBusGProxy *proxy; GError *error; gboolean login_ok = TRUE; for (; argc-- > 0; ++argv) { if (!strncmp (*argv, "debug", 5)) { debug++; } if (!strncmp (*argv, "try_first_pass", 14)) { try_first_pass++; } } /* Initialize GType system */ if (debug) { pam_syslog (pamh, LOG_INFO, "Initializing GType system."); } g_type_init(); /* Get system bus */ if (debug) { pam_syslog (pamh, LOG_INFO, "Getting system bus."); } error = NULL; bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); if (bus == NULL) { g_error_free (error); return PAM_AUTHINFO_UNAVAIL; } /* Create a D-Bus proxy; NM_DBUS_* defined in NetworkManager.h */ if (debug) { pam_syslog (pamh, LOG_INFO, "Creating D-Bus proxy."); } proxy = dbus_g_proxy_new_for_name (bus, NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_IFACE_SETTINGS); const char *service, *username, *authtok; if (debug) { pam_syslog (pamh, LOG_INFO, "Getting items."); } pam_get_item (pamh, PAM_SERVICE, (const void **)&service); if (pam_get_user (pamh, &username, NULL) != PAM_SUCCESS) { pam_syslog (pamh, LOG_ERR, "Couldn't determine username."); return PAM_AUTHINFO_UNAVAIL; } /* * try_first_pass works with simple password authentication. */ if (try_first_pass) { if (pam_get_item (pamh, PAM_AUTHTOK, (const void **)&authtok) != PAM_SUCCESS) { pam_syslog (pamh, LOG_ERR, "Couldn't obtain PAM_AUTHTOK from the pam stack."); authtok = NULL; } } if (authtok == NULL) { if (pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &authtok, "Password:"******"Couldn't obtain password from pam_prompt."); return PAM_AUTHINFO_UNAVAIL; } } /* Add a connection */ if (debug) { pam_syslog (pamh, LOG_INFO, "Adding network connection."); } add_connection (pamh, proxy, "__802.1x connection__", username, authtok); g_object_unref (proxy); dbus_g_connection_unref (bus); if (debug) { pam_syslog (pamh, LOG_INFO, "Authentication finished."); } //return login_ok ? PAM_SUCCESS : PAM_AUTH_ERR; return PAM_SUCCESS; }
// CALLED BY PAM_AUTHENTICATE PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) { module_config *cfg = NULL; user_config *user_cfg = NULL; int retval; unsigned int trial; const char *authtok = NULL; retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &authtok); if (retval != PAM_SUCCESS || (authtok != NULL && !strcmp(authtok, AUTHTOK_INCORRECT))) { D(("Previous authentication failed, let's stop here!")); return PAM_AUTH_ERR; } retval = parse_config(pamh, argc, argv, &cfg); //CHECK PAM CONFIGURATION if (retval == CONFIG_ERROR) { D(("Invalid configuration")); pam_syslog(pamh, LOG_ERR, "Invalid parameters to pam_2fa module"); pam_error(pamh, "Sorry, 2FA Pam Module is misconfigured, please contact admins!\n"); return PAM_AUTH_ERR; } // Get User configuration user_cfg = get_user_config(pamh, cfg); if(!user_cfg) { pam_syslog(pamh, LOG_INFO, "Unable to get user configuration"); // cleanup free_config(cfg); return PAM_AUTH_ERR; } const auth_mod *available_mods[4] = { NULL, NULL, NULL, NULL }; int menu_len = 0; if (cfg->gauth_enabled && user_cfg->gauth_login[0] != '\0') { #ifdef HAVE_CURL ++menu_len; available_mods[menu_len] = &gauth_auth; #else DBG(("GAuth configured, but CURL not compiled (should never happen!)")); #endif } if (cfg->sms_enabled && user_cfg->sms_mobile[0] != '\0') { ++menu_len; available_mods[menu_len] = &sms_auth; } if (cfg->yk_enabled && user_cfg->yk_publicids) { #ifdef HAVE_YKCLIENT ++menu_len; available_mods[menu_len] = &yk_auth; #else DBG(("Yubikey configured, but ykclient not compiled (should never happen!)")); #endif } retval = PAM_AUTH_ERR; for (trial = 0; trial < cfg->retry && retval != PAM_SUCCESS; ++trial) { const auth_mod *selected_auth_mod = NULL; char *user_input = NULL; if (menu_len > 1) { size_t user_input_len; int i = 1; pam_info(pamh, "Login for %s:\n", user_cfg->username); for (i = 1; i <= menu_len; ++i) { pam_info(pamh, " %d. %s", i, available_mods[i]->name); } if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_input, "\nOption (1-%d): ", menu_len) != PAM_SUCCESS) { pam_syslog(pamh, LOG_INFO, "Unable to get 2nd factors for user '%s'", user_cfg->username); pam_error(pamh, "Unable to get user input"); retval = PAM_AUTH_ERR; break; } user_input_len = user_input ? strlen(user_input) : 0; for (i = 1; i <= menu_len; ++i) { if (available_mods[i]->pre_auth == NULL && available_mods[i]->otp_len) { if (user_input_len == available_mods[i]->otp_len) { selected_auth_mod = available_mods[i]; break; } } } if (selected_auth_mod == NULL) { if (user_input_len == 1 && user_input[0] >= '1' && user_input[0] <= menu_len + '0') { selected_auth_mod = available_mods[user_input[0] - '0']; free(user_input); user_input = NULL; } else { pam_error(pamh, "Invalid input"); free(user_input); user_input = NULL; } } } else if (menu_len == 1) { selected_auth_mod = available_mods[1]; } else { pam_syslog(pamh, LOG_INFO, "No supported 2nd factor for user '%s'", user_cfg->username); pam_error(pamh, "No supported 2nd factors for user '%s'", user_cfg->username); retval = PAM_AUTH_ERR; break; } if (selected_auth_mod != NULL) { void * pre_auth_data = NULL; if (selected_auth_mod->pre_auth != NULL) { pre_auth_data = selected_auth_mod->pre_auth(pamh, user_cfg, cfg); if (pre_auth_data == NULL) continue; } if (user_input == NULL) { if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_input, "%s", selected_auth_mod->prompt) != PAM_SUCCESS) { pam_syslog(pamh, LOG_INFO, "Unable to get %s", selected_auth_mod->prompt); pam_error(pamh, "Unable to get user input"); free(pre_auth_data); retval = PAM_AUTH_ERR; break; } } retval = selected_auth_mod->do_auth(pamh, user_cfg, cfg, user_input, pre_auth_data); free(user_input); } } // final cleanup free_user_config(user_cfg); free_config(cfg); return retval; }
static security_context_t config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug) { security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *response=NULL; char *type=NULL; char resp_val = 0; pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon); while (1) { if (query_response(pamh, _("Would you like to enter a different role or level?"), "n", &response, debug) == PAM_SUCCESS) { resp_val = response[0]; _pam_drop(response); } else { resp_val = 'N'; } if ((resp_val == 'y') || (resp_val == 'Y')) { if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; /* Allow the user to enter role and level individually */ if (query_response(pamh, _("role:"), context_role_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (get_default_type(response, &type)) { pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response); _pam_drop(response); continue; } else { if (context_role_set(new_context, response)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } } _pam_drop(response); if (mls_enabled) { if (use_current_range) { security_context_t mycon = NULL; context_t my_context; if (getcon(&mycon) != 0) goto fail_set; my_context = context_new(mycon); if (my_context == NULL) { freecon(mycon); goto fail_set; } freecon(mycon); if (context_range_set(new_context, context_range_get(my_context))) { context_free(my_context); goto fail_set; } context_free(my_context); } else if (query_response(pamh, _("level:"), context_range_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { if (context_range_set(new_context, response)) goto fail_set; } _pam_drop(response); } if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context)); /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); if (newcon == NULL) goto fail_set; context_free(new_context); /* we have to check that this user is allowed to go into the range they have specified ... role is tied to an seuser, so that'll be checked at setexeccon time */ if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); send_audit_message(pamh, 0, defaultcon, newcon); free(newcon); goto fail_range; } return newcon; } else { send_audit_message(pamh, 0, defaultcon, context_str(new_context)); send_text(pamh,_("Not a valid security context"),debug); } context_free(new_context); /* next time around allocates another */ } else return strdup(defaultcon); } /* end while */ return NULL; fail_set: free(type); _pam_drop(response); context_free (new_context); send_audit_message(pamh, 0, defaultcon, NULL); fail_range: return NULL; }
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *values[] = { "\x70\x72", // "pr" => pierre "\x70\x70", // "pp" => papier "\x63\x73"}; // "cs" => ciseaux char prompt_text[32] = ""; const char *want = ""; char *response = NULL; int debug = 0; int ret, fd, r, i; unsigned char c; for (i = 0; i < argc; i++) { if (strcmp(argv[i], "debug") == 0) { debug = 1; break; } } r = -1; for (i = 0; i < argc; i++) { if (strncmp(argv[i], "throw=", 6) == 0) { r = atol(argv[i] + 6) % 3; break; } } if (r == -1) { r = 0; fd = open("/dev/urandom", O_RDONLY); if (fd != -1) { c = 0; do { ret = read(fd, &c, 1); } while ( ((ret == 1) && (c == 0xff)) || ((ret == -1) && (errno == EINTR)) ); /* We drop 0xff here to avoid a variation on * Bleichenbacher's attack. */ r = c / 85; close(fd); } else { /* Something is wrong with /dev/urandom */ return PAM_CONV_ERR; } } strcpy(prompt_text, values[(r % 3)]); want = values[((r + 1) % 3)]; if (debug) { pam_syslog(pamh, LOG_DEBUG, "challenge is \"%s\", " "expected response is \"%s\"", prompt_text, want); } ret = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &response, "%s: ", prompt_text); if (ret != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "conversation error"); return PAM_CONV_ERR; } if ((response != NULL) && (strcasecmp(response, want) == 0)) { ret = PAM_SUCCESS; } else { ret = PAM_AUTH_ERR; } if (response) { _pam_overwrite(response); free(response); } return ret; }
/** * @brief Check for allowance to access the node at pspam plugin * * Check for the allowance of the user @a user coming from the remote * host @a rhost to access the local node. For this the local pspam * plugin will be accesses in order figure out if the user currently * has a running batch-job on the node or is marked as an adminuser. * * Access might be denied (i.e. PSPAM_RES_DENY is returned) if the * communication to the pspam plugin fails or some problem in the * answer is detected. Otherwise pspam plugin's decision is returned. * * @param uName Username of the user to check * * @param rhost Hostname the user is coming from * * @return pspam plugin's decision is returned unless the * communication to the plugin failed. In the latter case * PSPAM_RES_DENY is returned (which might be a proper answer of the * pspam plugin, too). */ static PSPAMResult_t checkPsPamAllowance(const char *uName, const char *rhost) { int sock = openConnection(pspamSocketName); PSPAMResult_t res; PS_SendDB_t data = { .bufUsed = 0, .useFrag = false }; int written; if (sock == -1) { elog("connection to local plugin failed: %s", strerror(errno)); return PSPAM_RES_DENY; } initSerialBuf(0); /* add length placeholder */ addInt32ToMsg(0, &data); /* add command */ addInt32ToMsg(PSPAM_CMD_SESS_OPEN, &data); /* add ssh pid */ addPidToMsg(getpid(), &data); /* add ssh sid */ addPidToMsg(getsid(0), &data); /* add username */ addStringToMsg(uName, &data); /* add remote host */ addStringToMsg(rhost, &data); /* add correct msg len (without length) at placeholder */ *(int32_t *)data.buf = data.bufUsed - sizeof(int32_t); written = writeToPspam(sock, data.buf, data.bufUsed); finalizeSerial(); if (written != (int)data.bufUsed) { elog("sending pspam auth request failed"); return PSPAM_RES_DENY; } if (verbose > 2) { ilog("sending req(%i): %s@%s pid %u", sock, uName, rhost, getpid()); } if (!readFromPspam(sock, &res, sizeof(res))) { close(sock); return PSPAM_RES_DENY; } close(sock); if (verbose > 2) { ilog("reply(%i): %s@%s res %u", sock, uName, rhost, res); } return res; } /** * @brief Check for allowance to access the node * * Check for the allowance of the user @a user coming from the remote * host @a rhost to access the local node. Allowance is granted either * via a white-list of usernames passed as an option to the PAM module * or by the local pspam plugin which might be contacted. * * @param uName Username of the user to check * * @param rhost Hostname the user is coming from * * @return PAM_SUCCESS is returned in order to grant access. Otherwise * PAM_AUTH_ERR is returned. */ static int checkAllowance(const char *uName, const char *rhost) { PSPAMResult_t res; /* check if the user is in the authorized user list */ if (isAuthorizedUser(uName)) { if (verbose > 1) { ilog("grant access to %s@%s (authorized list)", uName, rhost); } return PAM_SUCCESS; } /* ask pspam if user has a batch job running and is allowed to connect */ res = checkPsPamAllowance(uName, rhost); switch (res) { case PSPAM_RES_BATCH: case PSPAM_RES_ADMIN_USER: if (verbose > 1) { ilog("grant access to %s@%s (%s)", uName, rhost, (res == PSPAM_RES_BATCH) ? "batch job" : "ps admin user"); } return PAM_SUCCESS; case PSPAM_RES_DENY: case PSPAM_RES_PROLOG: if (verbose > 0) { ilog("deny access to %s@%s (%s)", uName, rhost, (res == PSPAM_RES_PROLOG) ? "prologue" : "no job"); } } if (!quiet) { char hName[HOSTNAME_LEN]; if (gethostname(hName, sizeof(hName)) == -1) { strncpy(hName, "this node", sizeof(hName)); } switch (res) { case PSPAM_RES_DENY: pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: user '%s' without" " running jobs on %s, access denied.\n", uName, hName); break; case PSPAM_RES_PROLOG: pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: prologue running on" " %s, access denied.\n", hName); break; default: pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: access denied.\n"); } } return PAM_AUTH_ERR; }