22575: Remove extra ;, From Dennis Davis.
[heimdal.git] / appl / popper / pop_pass.c
blobabd6d69fc7f50788eb6e49f2f13662fb75bb219a
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 KRB4
15 static int
16 krb4_verify_password (POP *p)
18 int status;
19 char lrealm[REALM_SZ];
20 char tkt[MaxPathLen];
22 status = krb_get_lrealm(lrealm,1);
23 if (status == KFAILURE) {
24 pop_log(p, POP_PRIORITY, "%s: (%s.%s@%s) %s", p->client,
25 p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
26 krb_get_err_text(status));
27 return 1;
29 snprintf(tkt, sizeof(tkt), "%s_popper.%u", TKT_ROOT, (unsigned)getpid());
30 krb_set_tkt_string (tkt);
32 status = krb_verify_user(p->user, "", lrealm,
33 p->pop_parm[1], KRB_VERIFY_SECURE, "pop");
34 dest_tkt(); /* no point in keeping the tickets */
35 return status;
37 #endif /* KRB4 */
39 #ifdef KRB5
40 static int
41 krb5_verify_password (POP *p)
43 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
44 krb5_get_init_creds_opt *get_options;
45 krb5_verify_init_creds_opt verify_options;
46 krb5_error_code ret;
47 krb5_principal client, server;
48 krb5_creds creds;
50 ret = krb5_get_init_creds_opt_alloc (p->context, &get_options);
51 if (ret) {
52 pop_log(p, POP_PRIORITY, "krb5_get_init_creds_opt_init: %s",
53 krb5_get_err_text (p->context, ret));
54 return 1;
57 krb5_get_init_creds_opt_set_preauth_list (get_options,
58 pre_auth_types,
59 1);
61 krb5_verify_init_creds_opt_init (&verify_options);
63 ret = krb5_parse_name (p->context, p->user, &client);
64 if (ret) {
65 pop_log(p, POP_PRIORITY, "krb5_parse_name: %s",
66 krb5_get_err_text (p->context, ret));
67 return 1;
70 ret = krb5_get_init_creds_password (p->context,
71 &creds,
72 client,
73 p->pop_parm[1],
74 NULL,
75 NULL,
77 NULL,
78 get_options);
79 krb5_get_init_creds_opt_free(p->context, get_options);
80 if (ret) {
81 pop_log(p, POP_PRIORITY,
82 "krb5_get_init_creds_password: %s",
83 krb5_get_err_text (p->context, ret));
84 return 1;
87 ret = krb5_sname_to_principal (p->context,
88 p->myhost,
89 "pop",
90 KRB5_NT_SRV_HST,
91 &server);
92 if (ret) {
93 pop_log(p, POP_PRIORITY,
94 "krb5_get_init_creds_password: %s",
95 krb5_get_err_text (p->context, ret));
96 return 1;
99 ret = krb5_verify_init_creds (p->context,
100 &creds,
101 server,
102 NULL,
103 NULL,
104 &verify_options);
105 krb5_free_principal (p->context, client);
106 krb5_free_principal (p->context, server);
107 krb5_free_cred_contents (p->context, &creds);
108 return ret;
110 #endif
112 * pass: Obtain the user password from a POP client
116 login_user(POP *p)
118 struct stat st;
119 struct passwd *pw;
121 /* Look for the user in the password file */
122 if ((pw = k_getpwnam(p->user)) == NULL) {
123 pop_log(p, POP_PRIORITY, "user %s (from %s) not found",
124 p->user, p->ipaddr);
125 return pop_msg(p, POP_FAILURE, "Login incorrect.");
128 pop_log(p, POP_INFO, "login from %s as %s", p->ipaddr, p->user);
130 /* Build the name of the user's maildrop */
131 snprintf(p->drop_name, sizeof(p->drop_name), "%s/%s", POP_MAILDIR, p->user);
132 if(stat(p->drop_name, &st) < 0 || !S_ISDIR(st.st_mode)){
133 /* Make a temporary copy of the user's maildrop */
134 /* and set the group and user id */
135 if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE);
137 /* Get information about the maildrop */
138 if (pop_dropinfo(p) != POP_SUCCESS) return(POP_FAILURE);
139 } else {
140 if(changeuser(p, pw) != POP_SUCCESS) return POP_FAILURE;
141 if(pop_maildir_info(p) != POP_SUCCESS) return POP_FAILURE;
143 /* Initialize the last-message-accessed number */
144 p->last_msg = 0;
145 return POP_SUCCESS;
149 pop_pass (POP *p)
151 struct passwd *pw;
152 int i;
153 int status;
155 /* Make one string of all these parameters */
157 for (i = 1; i < p->parm_count; ++i)
158 p->pop_parm[i][strlen(p->pop_parm[i])] = ' ';
160 /* Look for the user in the password file */
161 if ((pw = k_getpwnam(p->user)) == NULL)
162 return (pop_msg(p,POP_FAILURE,
163 "Password supplied for \"%s\" is incorrect.",
164 p->user));
166 if (p->kerberosp) {
167 #ifdef KRB4
168 if (p->version == 4) {
169 if(kuserok (&p->kdata, p->user)) {
170 pop_log(p, POP_PRIORITY,
171 "%s: (%s.%s@%s) tried to retrieve mail for %s.",
172 p->client, p->kdata.pname, p->kdata.pinst,
173 p->kdata.prealm, p->user);
174 return(pop_msg(p,POP_FAILURE,
175 "Popping not authorized"));
177 pop_log(p, POP_INFO, "%s: %s.%s@%s -> %s",
178 p->ipaddr,
179 p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
180 p->user);
181 } else
182 #endif /* KRB4 */
183 #ifdef KRB5
184 if (p->version == 5) {
185 char *name;
187 if (!krb5_kuserok (p->context, p->principal, p->user)) {
188 pop_log (p, POP_PRIORITY,
189 "krb5 permission denied");
190 return pop_msg(p, POP_FAILURE,
191 "Popping not authorized");
193 if(krb5_unparse_name (p->context, p->principal, &name) == 0) {
194 pop_log(p, POP_INFO, "%s: %s -> %s",
195 p->ipaddr, name, p->user);
196 free (name);
198 } else {
199 pop_log (p, POP_PRIORITY, "kerberos authentication failed");
200 return pop_msg (p, POP_FAILURE,
201 "kerberos authentication failed");
203 #endif
205 } else {
206 /* We don't accept connections from users with null passwords */
207 if (pw->pw_passwd == NULL)
208 return (pop_msg(p,
209 POP_FAILURE,
210 "Password supplied for \"%s\" is incorrect.",
211 p->user));
213 #ifdef OTP
214 if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
215 /* pass OK */;
216 else
217 #endif
218 /* Compare the supplied password with the password file entry */
219 if (p->auth_level != AUTH_NONE)
220 return pop_msg(p, POP_FAILURE,
221 "Password supplied for \"%s\" is incorrect.",
222 p->user);
223 else if (!strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))
224 /* pass OK */;
225 else {
226 int ret = -1;
227 #ifdef KRB4
228 ret = krb4_verify_password (p);
229 #endif
230 #ifdef KRB5
231 if(ret)
232 ret = krb5_verify_password (p);
233 #endif
234 if(ret)
235 return pop_msg(p, POP_FAILURE,
236 "Password incorrect");
239 status = login_user(p);
240 if(status != POP_SUCCESS)
241 return status;
243 /* Authorization completed successfully */
244 return (pop_msg (p, POP_SUCCESS,
245 "%s has %d message(s) (%ld octets).",
246 p->user, p->msg_count, p->drop_size));