1/* 2 * Copyright (c) 1989 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7#include <popper.h> 8#ifdef HAVE_CRYPT_H 9#include <crypt.h> 10#endif 11 12RCSID("$Id$"); 13 14#ifdef KRB5 15static int 16krb5_verify_password (POP *p) 17{ 18 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP}; 19 krb5_get_init_creds_opt *get_options; 20 krb5_verify_init_creds_opt verify_options; 21 krb5_error_code ret; 22 krb5_principal client, server; 23 krb5_creds creds; 24 25 ret = krb5_get_init_creds_opt_alloc (p->context, &get_options); 26 if (ret) { 27 pop_log(p, POP_PRIORITY, "krb5_get_init_creds_opt_alloc: %s", 28 krb5_get_err_text (p->context, ret)); 29 return 1; 30 } 31 32 krb5_get_init_creds_opt_set_preauth_list (get_options, 33 pre_auth_types, 34 1); 35 36 krb5_verify_init_creds_opt_init (&verify_options); 37 38 ret = krb5_parse_name (p->context, p->user, &client); 39 if (ret) { 40 krb5_get_init_creds_opt_free(p->context, get_options); 41 pop_log(p, POP_PRIORITY, "krb5_parse_name: %s", 42 krb5_get_err_text (p->context, ret)); 43 return 1; 44 } 45 46 ret = krb5_get_init_creds_password (p->context, 47 &creds, 48 client, 49 p->pop_parm[1], 50 NULL, 51 NULL, 52 0, 53 NULL, 54 get_options); 55 krb5_get_init_creds_opt_free(p->context, get_options); 56 if (ret) { 57 pop_log(p, POP_PRIORITY, 58 "krb5_get_init_creds_password: %s", 59 krb5_get_err_text (p->context, ret)); 60 return 1; 61 } 62 63 ret = krb5_sname_to_principal (p->context, 64 p->myhost, 65 "pop", 66 KRB5_NT_SRV_HST, 67 &server); 68 if (ret) { 69 pop_log(p, POP_PRIORITY, 70 "krb5_get_init_creds_password: %s", 71 krb5_get_err_text (p->context, ret)); 72 return 1; 73 } 74 75 ret = krb5_verify_init_creds (p->context, 76 &creds, 77 server, 78 NULL, 79 NULL, 80 &verify_options); 81 krb5_free_principal (p->context, client); 82 krb5_free_principal (p->context, server); 83 krb5_free_cred_contents (p->context, &creds); 84 return ret; 85} 86#endif 87/* 88 * pass: Obtain the user password from a POP client 89 */ 90 91int 92login_user(POP *p) 93{ 94 struct stat st; 95 struct passwd *pw; 96 97 /* Look for the user in the password file */ 98 if ((pw = k_getpwnam(p->user)) == NULL) { 99 pop_log(p, POP_PRIORITY, "user %s (from %s) not found", 100 p->user, p->ipaddr); 101 return pop_msg(p, POP_FAILURE, "Login incorrect."); 102 } 103 104 pop_log(p, POP_INFO, "login from %s as %s", p->ipaddr, p->user); 105 106 /* Build the name of the user's maildrop */ 107 snprintf(p->drop_name, sizeof(p->drop_name), "%s/%s", POP_MAILDIR, p->user); 108 if(stat(p->drop_name, &st) < 0 || !S_ISDIR(st.st_mode)){ 109 /* Make a temporary copy of the user's maildrop */ 110 /* and set the group and user id */ 111 if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE); 112 113 /* Get information about the maildrop */ 114 if (pop_dropinfo(p) != POP_SUCCESS) return(POP_FAILURE); 115 } else { 116 if(changeuser(p, pw) != POP_SUCCESS) return POP_FAILURE; 117 if(pop_maildir_info(p) != POP_SUCCESS) return POP_FAILURE; 118 } 119 /* Initialize the last-message-accessed number */ 120 p->last_msg = 0; 121 return POP_SUCCESS; 122} 123 124int 125pop_pass (POP *p) 126{ 127 struct passwd *pw; 128 int i; 129 int status; 130 131 /* Make one string of all these parameters */ 132 133 for (i = 1; i < p->parm_count; ++i) 134 p->pop_parm[i][strlen(p->pop_parm[i])] = ' '; 135 136 /* Look for the user in the password file */ 137 if ((pw = k_getpwnam(p->user)) == NULL) 138 return (pop_msg(p,POP_FAILURE, 139 "Password supplied for \"%s\" is incorrect.", 140 p->user)); 141 142 if (p->kerberosp) { 143#ifdef KRB5 144 if (p->version == 5) { 145 char *name; 146 147 if (!krb5_kuserok (p->context, p->principal, p->user)) { 148 pop_log (p, POP_PRIORITY, 149 "krb5 permission denied"); 150 return pop_msg(p, POP_FAILURE, 151 "Popping not authorized"); 152 } 153 if(krb5_unparse_name (p->context, p->principal, &name) == 0) { 154 pop_log(p, POP_INFO, "%s: %s -> %s", 155 p->ipaddr, name, p->user); 156 free (name); 157 } 158 } else { 159 pop_log (p, POP_PRIORITY, "kerberos authentication failed"); 160 return pop_msg (p, POP_FAILURE, 161 "kerberos authentication failed"); 162 } 163#endif 164 { } 165 } else { 166 /* We don't accept connections from users with null passwords */ 167 if (pw->pw_passwd == NULL) 168 return (pop_msg(p, 169 POP_FAILURE, 170 "Password supplied for \"%s\" is incorrect.", 171 p->user)); 172 173#ifdef OTP 174 if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0) 175 /* pass OK */; 176 else 177#endif 178 /* Compare the supplied password with the password file entry */ 179 if (p->auth_level != AUTH_NONE) 180 return pop_msg(p, POP_FAILURE, 181 "Password supplied for \"%s\" is incorrect.", 182 p->user); 183 else if (!strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) 184 /* pass OK */; 185 else { 186 int ret = -1; 187#ifdef KRB5 188 if(ret) 189 ret = krb5_verify_password (p); 190#endif 191 if(ret) 192 return pop_msg(p, POP_FAILURE, 193 "Password incorrect"); 194 } 195 } 196 status = login_user(p); 197 if(status != POP_SUCCESS) 198 return status; 199 200 /* Authorization completed successfully */ 201 return (pop_msg (p, POP_SUCCESS, 202 "%s has %d message(s) (%ld octets).", 203 p->user, p->msg_count, p->drop_size)); 204} 205