/* * skey_authenticate() * * Used when calling program will allow input of the user's * response to the challenge. * * Returns: 0 success, -1 failure * */ int skey_authenticate(char *username) { char pbuf[SKEY_MAX_PW_LEN+1], skeyprompt[SKEY_MAX_CHALLENGE+1]; struct skey skey; int i; /* Get the S/Key challenge (may be fake) */ i = skeychallenge(&skey, username, skeyprompt); (void)fprintf(stderr, "%s\nResponse: ", skeyprompt); (void)fflush(stderr); /* Time out on user input after 2 minutes */ tgetline(fileno(stdin), pbuf, sizeof(pbuf), 120); sevenbit(pbuf); (void)rewind(stdin); /* Is it a valid response? */ if (i == 0 && skeyverify(&skey, pbuf) == 0) { if (skey.n < 5) { (void)fprintf(stderr, "\nWarning! Key initialization needed soon. (%d logins left)\n", skey.n); } return (0); } return (-1); }
/* * skey_keyinfo() * * Returns the current sequence number and * seed for the passed user. * */ char * skey_keyinfo(char *username) { static char str[SKEY_MAX_CHALLENGE]; struct skey skey; int i; i = skeychallenge(&skey, username, str); if (i == -1) return (0); if (skey.keyfile != NULL) { fclose(skey.keyfile); skey.keyfile = NULL; } return (str); }
int mm_answer_skeyquery(int socket, Buffer *m) { struct skey skey; char challenge[1024]; u_int success; success = skeychallenge(&skey, authctxt->user, challenge) < 0 ? 0 : 1; buffer_clear(m); buffer_put_int(m, success); if (success) buffer_put_cstring(m, challenge); debug3("%s: sending challenge success: %u", __func__, success); mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); return (0); }
int mm_answer_skeyquery(int socket, Buffer *m) { struct skey skey; char challenge[1024]; int res; res = skeychallenge(&skey, authctxt->user, challenge); buffer_clear(m); buffer_put_int(m, res); if (res != -1) buffer_put_cstring(m, challenge); debug3("%s: sending challenge res: %d", __func__, res); mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); return (0); }
int skey_query(void *ctx, char **name, char **infotxt, u_int* numprompts, char ***prompts, u_int **echo_on) { Authctxt *authctxt = ctx; char challenge[1024]; struct skey skey; if (skeychallenge(&skey, authctxt->user, challenge, sizeof(challenge)) == -1) return -1; *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xcalloc(*numprompts, sizeof(char *)); *echo_on = xcalloc(*numprompts, sizeof(u_int)); xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT); return 0; }
int pw_auth (const char *cipher, const char *user, int reason, const char *input) { char prompt[1024]; char *clear = NULL; const char *cp; int retval; #ifdef SKEY int use_skey = 0; char challenge_info[40]; struct skey skey; #endif /* * There are programs for adding and deleting authentication data. */ if (reason == PW_ADD || reason == PW_DELETE) return 0; /* * There are even programs for changing the user name ... */ if (reason == PW_CHANGE && input != (char *) 0) return 0; /* * WARNING: * * When we change a password and we are root, we don't prompt. * This is so root can change any password without having to * know it. This is a policy decision that might have to be * revisited. */ if (reason == PW_CHANGE && getuid () == 0) return 0; /* * WARNING: * * When we are logging in a user with no ciphertext password, * we don't prompt for the password or anything. In reality * the user could just hit <ENTER>, so it doesn't really * matter. */ if (cipher == (char *) 0 || *cipher == '\0') return 0; #ifdef SKEY /* * If the user has an S/KEY entry show them the pertinent info * and then we can try validating the created cyphertext and the SKEY. * If there is no SKEY information we default to not using SKEY. */ if (skeychallenge (&skey, user, challenge_info) == 0) use_skey = 1; #endif /* * Prompt for the password as required. FTPD and REXECD both * get the cleartext password for us. */ if (reason != PW_FTP && reason != PW_REXEC && !input) { if (!(cp = getdef_str ("LOGIN_STRING"))) cp = _(PROMPT); #ifdef SKEY if (use_skey) printf ("[%s]\n", challenge_info); #endif snprintf (prompt, sizeof prompt, cp, user); clear = getpass (prompt); if (!clear) { static char c[1]; c[0] = '\0'; clear = c; } input = clear; } /* * Convert the cleartext password into a ciphertext string. * If the two match, the return value will be zero, which is * SUCCESS. Otherwise we see if SKEY is being used and check * the results there as well. */ retval = strcmp (pw_encrypt (input, cipher), cipher); #ifdef SKEY /* * If (1) The password fails to match, and * (2) The password is empty and * (3) We are using OPIE or S/Key, then * ...Re-prompt, with echo on. * -- AR 8/22/1999 */ if (retval && !input[0] && (use_skey)) { strncat (prompt, "(Echo on) ", (sizeof (prompt) - strlen (prompt))); clear = getpass_with_echo (prompt); if (!clear) { static char c[1]; c[0] = '\0'; clear = c; } input = clear; } if (retval && use_skey) { int passcheck = -1; if (skeyverify (&skey, input) == 0) passcheck = skey.n; if (passcheck > 0) retval = 0; } #endif /* * Things like RADIUS authentication may need the password - * if the external variable wipe_clear_pass is zero, we will * not wipe it (the caller should wipe clear_pass when it is * no longer needed). --marekm */ clear_pass = clear; if (wipe_clear_pass && clear && *clear) strzero (clear); return retval; }