void auth_static_init(const char *passwd) { char *key; srand(time(NULL)); key = crypt(passwd, gen_salt()); strcpy(static_key, key); }
char * gen_passwd(char *plaintext) { char * passwd = crypt(plaintext, gen_salt()); if (!passwd) { perror("gen_passwd"); } return(passwd); }
char *ast_crypt_encrypt(const char *key) { char salt[MAX_SALT_LEN] = {}; while (gen_salt(salt, sizeof(salt)) == 0) { char *crypted = ast_crypt(key, salt); if (crypted) { return crypted; } } return NULL; }
void set_password(myuser_t *mu, const char *newpassword) { if (mu == NULL || newpassword == NULL) return; /* if we can, try to crypt it */ if (crypto_module_loaded) { mu->flags |= MU_CRYPTPASS; mowgli_strlcpy(mu->pass, crypt_string(newpassword, gen_salt()), PASSLEN); } else { mu->flags &= ~MU_CRYPTPASS; /* just in case */ mowgli_strlcpy(mu->pass, newpassword, PASSLEN); } }
static void ns_cmd_generatehash(sourceinfo_t *si, int parc, char *parv[]) { char *pass = parv[0]; char hash[PASSLEN]; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "GENERATEHASH"); command_fail(si, fault_needmoreparams, _("Syntax: GENERATEHASH <password>")); return; } if (crypto_module_loaded) { mowgli_strlcpy(hash, crypt_string(pass, gen_salt()), PASSLEN); command_success_string(si, hash, "Hash is: %s", hash); } else command_success_nodata(si, "No crypto module loaded so could not hash anything."); logcommand(si, CMDLOG_GET, "GENERATEHASH"); }
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *name = parv[0]; char *newpass = NULL; char *key; metadata_t *md; enum specialoperation op = op_none; bool ismarked = false; char cmdtext[NICKLEN + 20]; hook_user_needforce_t needforce_hdata; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!strcasecmp(parv[1], "FORCE")) op = op_force; else if (!strcasecmp(parv[1], "CLEAR")) op = op_clear; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS"); command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]")); return; } } if (!(mu = myuser_find_by_nick(name))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name); return; } if (is_soper(mu) && !has_priv(si, PRIV_ADMIN)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (is SOPER)", name); command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to send the password."), name, PRIV_ADMIN); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if ((md = metadata_find(mu, "private:mark:setter"))) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked by %s."), entity(mu)->name, md->value); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } needforce_hdata.si = si; needforce_hdata.mu = mu; needforce_hdata.allowed = 1; hook_call_user_needforce(&needforce_hdata); if (!needforce_hdata.allowed) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked."), entity(mu)->name); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { metadata_delete(mu, "private:setpass:key"); metadata_delete(mu, "private:sendpass:sender"); metadata_delete(mu, "private:sendpass:timestamp"); logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name); } else command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name); return; } if (MOWGLI_LIST_LENGTH(&mu->logins) > 0) { command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } if (command_find(si->service->commands, "SETPASS")) { if (metadata_find(mu, "private:setpass:key")) { command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name); command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name); return; } if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); key = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(key); return; } metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); free(key); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); } else { if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name); newpass = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, newpass)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(newpass); return; } set_password(mu, newpass); free(newpass); command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (mu->flags & MU_NOPASSWORD) { mu->flags &= ~MU_NOPASSWORD; command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "NOPASSWORD", entity(mu)->name); } } }
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *name = parv[0]; char *key; enum specialoperation op = op_none; bool ismarked = false; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!has_priv(si, PRIV_USER_SENDPASS)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!strcasecmp(parv[1], "FORCE")) op = op_force; else if (!strcasecmp(parv[1], "CLEAR")) op = op_clear; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS"); command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]")); return; } } if (!(mu = myuser_find_by_nick(name))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if (metadata_find(mu, "private:mark:setter")) { ismarked = true; /* don't want to disclose this, so just go ahead... */ } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { metadata_delete(mu, "private:setpass:key"); logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name); } else command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name); return; } if (MOWGLI_LIST_LENGTH(&mu->logins) > 0) { command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_success_nodata(si, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } if (metadata_find(mu, "private:setpass:key")) { command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name); if (has_priv(si, PRIV_USER_SENDPASS)) command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name); return; } key = random_string(12); if (sendemail(si->su != NULL ? si->su : si->service->me, EMAIL_SETPASS, mu, key)) { metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to the corresponding email address."), entity(mu)->name); if (ismarked) wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); } else command_fail(si, fault_emailfail, _("Email send failed.")); free(key); }
static int mech_step(sasl_session_t *p, char *message, int len, char **out, int *out_len) { struct crypt_status *s = (struct crypt_status *)p->mechdata; myuser_t *mu; s->stage++; if(s->stage == 1) /* C -> S: username + 16 bytes random data */ { char user[64]; if(len < 17) return ASASL_FAIL; /* Store client's random data & skip to username */ memcpy(s->client_data, message, 16); message += 16; len -= 16; /* Sanitize and check if user exists */ strlcpy(user, message, len > 63 ? 64 : len + 1); if(!(mu = myuser_find(user))) return ASASL_FAIL; p->username = strdup(user); /* Send salt from password to client, generating one if necessary */ if(mu->flags & MU_CRYPTPASS) { if(strlen(mu->pass) == 13) /* original DES type */ { *out_len = 2; *out = malloc(2); memcpy(*out, mu->pass, 2); } else if(*(mu->pass) == '$') /* FreeBSD MD5 type */ { *out_len = strlen(mu->pass) - 22; *out = malloc(*out_len); memcpy(*out, mu->pass, *out_len); (*out)[(*out_len) - 1] = '$'; } s->password = (unsigned char *) strdup(mu->pass); } else { s->password = (unsigned char *) strdup(crypt(mu->pass, gen_salt())); *out_len = 10; *out = strdup((char *)s->password); } return ASASL_MORE; } else if(s->stage == 2) /* C -> S: raw MD5 of server random data + client random data + crypted password */ { md5_state_t ctx; char hash[16]; if(len != 16) return ASASL_FAIL; md5_init(&ctx); md5_append(&ctx, s->server_data, 16); md5_append(&ctx, s->client_data, 16); md5_append(&ctx, s->password, strlen((char *)s->password)); md5_finish(&ctx, (unsigned char *) hash); if(!memcmp(message, hash, 16)) return ASASL_DONE; else return ASASL_FAIL; }else /* wtf? */ return ASASL_FAIL; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[]) { const char *user; char *password, *crypt_password, *cached_password; int pam_err, timestamp; /* identify user */ if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) return (pam_err); if (getpwnam(user) == NULL) return (PAM_USER_UNKNOWN); /* get password */ pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **)&password, NULL); if (pam_err == PAM_CONV_ERR) return (pam_err); if (pam_err != PAM_SUCCESS) return (PAM_AUTH_ERR); cached_password = NULL; if (!read_ticket(user, ×tamp, &cached_password)) { pam_err = PAM_AUTH_ERR; if (crypt_set_format("sha512")) crypt_password = crypt(password, gen_salt()); else crypt_password = NULL; goto done; } if ((crypt_password = crypt(password, cached_password)) != NULL && strcmp(crypt_password, cached_password) == 0) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); /* TODO: timeout should be an argument! */ if ((int)now.tv_sec > timestamp + TIMEOUT) { openpam_log(PAM_LOG_DEBUG, "expired auth ticket: %d > %d", (int)now.tv_sec, timestamp + TIMEOUT); pam_err = PAM_AUTH_ERR; } else { pam_err = PAM_SUCCESS; } } else { openpam_log(PAM_LOG_DEBUG, "passwords do not match"); pam_err = PAM_AUTH_ERR; } done: if (crypt_password != NULL) { char *cp; size_t len; len = strlen(crypt_password) + 1; if ((cp = calloc(len, sizeof(char))) != NULL && strlcpy(cp, crypt_password, len) < len) pam_set_data(pamh, "pam_auth_ticket", cp, cleanup); } free(cached_password); return (pam_err); }
/* * enable privileged mode */ int enable(int argc, char **argv) { char *p, *cpass; char salt[_PASSWORD_LEN]; char pass[_PASSWORD_LEN + 1]; switch (argc) { case 1: if (priv == 1) return 0; /* try to read pass */ if (!(read_pass(pass, sizeof(pass)))) { if (errno == ENOENT) { /* no password file, so enable */ priv = 1; return 1; } else { /* cant read password file */ printf("%% Unable to read password: %s\n", strerror(errno)); return 0; } } p = getpass("Password:"******"%% Password incorrect\n"); return 0; } case 2: if (argv[1][0] == '?') { /* print help */ printf("%% enable\t\t\t\tenable privileged mode\n"); printf("%% enable ?\t\t\t\tShow Options\n"); printf("%% enable secret <password>\t\tSet password" "(plaintext)\n"); printf("%% enable secret <cipher> <hash>\t\tSet" " password(ciphertext)\n"); return 1; } else { printf("%% Invalid argument: %s\n", argv[1]); return 0; } case 3: if (!isprefix(argv[1], "secret")) { printf("%% Invalid argument: %s\n", argv[1]); return 0; } if (priv != 1) { printf("%% Privilege required\n"); return 0; } /* crypt plaintext and save as pass */ strlcpy(pass, argv[2], sizeof(pass)); gen_salt(salt, sizeof(salt)); cpass = strdup(crypt(pass, salt)); return (write_pass(cpass)); case 4: if (!isprefix(argv[1], "secret")) { printf("%% Invalid argument: %s\n", argv[2]); return 0; } if (!isprefix(argv[2], "blowfish")) { printf("%% Invalid cipher: %s\n", argv[3]); return 0; } /* privileged? */ if (priv != 1) { printf("%% Privilege required\n"); return 0; } /* set crypted pass */ strlcpy(pass, argv[3], sizeof(pass)); return (write_pass(pass)); default: printf("%% Too many arguments\n"); return 0; } }