s4:heimdal A real fix for bug 6801
[heimdal.git] / appl / popper / pop_pass.c
blobe7f9aeb809cdde73843c231e2dbc6d468abfddad
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 */
7 #include <popper.h>
8 #ifdef HAVE_CRYPT_H
9 #include <crypt.h>
10 #endif
12 RCSID("$Id$");
14 #ifdef KRB5
15 static int
16 krb5_verify_password (POP *p)
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;
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;
32 krb5_get_init_creds_opt_set_preauth_list (get_options,
33 pre_auth_types,
34 1);
36 krb5_verify_init_creds_opt_init (&verify_options);
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;
46 ret = krb5_get_init_creds_password (p->context,
47 &creds,
48 client,
49 p->pop_parm[1],
50 NULL,
51 NULL,
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;
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;
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;
86 #endif
88 * pass: Obtain the user password from a POP client
91 int
92 login_user(POP *p)
94 struct stat st;
95 struct passwd *pw;
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.");
104 pop_log(p, POP_INFO, "login from %s as %s", p->ipaddr, p->user);
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);
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;
119 /* Initialize the last-message-accessed number */
120 p->last_msg = 0;
121 return POP_SUCCESS;
125 pop_pass (POP *p)
127 struct passwd *pw;
128 int i;
129 int status;
131 /* Make one string of all these parameters */
133 for (i = 1; i < p->parm_count; ++i)
134 p->pop_parm[i][strlen(p->pop_parm[i])] = ' ';
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));
142 if (p->kerberosp) {
143 #ifdef KRB5
144 if (p->version == 5) {
145 char *name;
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");
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);
158 } else {
159 pop_log (p, POP_PRIORITY, "kerberos authentication failed");
160 return pop_msg (p, POP_FAILURE,
161 "kerberos authentication failed");
163 #endif
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));
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");
196 status = login_user(p);
197 if(status != POP_SUCCESS)
198 return status;
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));