freebsd-kauth-sig-t-20090512
[openafs.git] / src / kauth / user.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* This file provides the easiest, turn-key interface to the authication
11  * package. */
12
13 #include <afsconfig.h>
14 #if defined(UKERNEL)
15 #include "afs/param.h"
16 #else
17 #include <afs/param.h>
18 #endif
19
20 RCSID
21     ("$Header$");
22
23 #if defined(UKERNEL)
24 #include "afs/sysincludes.h"
25 #include "afsincludes.h"
26 #include "afs/stds.h"
27 #include "afs/com_err.h"
28 #include "afs/cellconfig.h"
29 #include "afs/auth.h"
30 #include "afs/ptint.h"
31 #include "afs/pterror.h"
32 #include "afs/ptserver.h"
33 #include "rx/rx.h"
34 #include "rx/rx_globals.h"
35 #include "rx/rxkad.h"
36 #include "afs/kauth.h"
37 #include "afs/kautils.h"
38 #include "afs/afsutil.h"
39 #else /* defined(UKERNEL) */
40 #include <afs/stds.h>
41 #include <signal.h>
42 #include <afs/com_err.h>
43 #ifdef AFS_NT40_ENV
44 #include <winsock2.h>
45 #else
46 #include <netinet/in.h>
47 #endif
48 #include <string.h>
49 #include <afs/cellconfig.h>
50 #include <afs/auth.h>
51 #include <afs/ptint.h>
52 #include <afs/pterror.h>
53 #include <afs/ptuser.h>
54 #include <afs/ptserver.h>
55 #include <afs/afsutil.h>
56 #include <rx/rx.h>
57 #include <rx/rx_globals.h>
58 #include <rx/rxkad.h>           /* max ticket lifetime */
59 #include <des.h>
60 #include <des_prototypes.h>
61 #include "kauth.h"
62 #include "kautils.h"
63 #endif /* defined(UKERNEL) */
64
65
66 afs_int32
67 GetTickets(char *name, char *instance, char *realm,
68            struct ktc_encryptionKey * key, Date lifetime,
69            afs_int32 * pwexpires, afs_int32 flags)
70 {
71     afs_int32 code;
72
73     code = ka_GetAuthToken(name, instance, realm, key, lifetime, pwexpires);
74     memset(key, 0, sizeof(*key));
75     if (code)
76         return code;
77     code = ka_GetAFSTicket(name, instance, realm, lifetime, flags);
78     return code;
79 }
80
81 /* 
82  * Requires that you already possess a TGT.
83  */
84 afs_int32
85 ka_GetAFSTicket(char *name, char *instance, char *realm, Date lifetime,
86                 afs_int32 flags)
87 {
88     afs_int32 code;
89     struct ktc_token token;
90     struct ktc_principal server, client;
91
92     code = ka_GetServerToken("afs", "", realm, lifetime, &token, /*new */ 1,
93                              /*dosetpag */ flags);
94     if (code)
95         return code;
96     if (ktc_OldPioctl()) {
97         int local;
98         char username[MAXKTCNAMELEN];
99         afs_int32 viceId;
100         int len;
101         char *whoami = "UserAuthenticate: ptserver";
102
103         strcpy(server.name, "afs");
104         strcpy(server.instance, "");
105         code = ka_ExpandCell(realm, server.cell, &local);
106         if (code)
107             return code;
108         code = pr_Initialize(0, AFSDIR_CLIENT_ETC_DIRPATH, server.cell);
109         if (code) {
110             afs_com_err(whoami, code, "initializing ptserver in cell '%s'",
111                     server.cell);
112             return 0;
113         }
114         len = strlen(name);
115         if (instance[0])
116             len += strlen(instance) + 1;
117         if (len >= sizeof(username)) {
118             fprintf(stderr, "user's name '%s'.'%s' would be too large\n",
119                     name, instance);
120             return 0;
121         }
122         strcpy(username, name);
123         if (instance[0]) {
124             strcat(username, ".");
125             strcat(username, instance);
126         }
127         code = pr_SNameToId(username, &viceId);
128         /* Before going further, shutdown the pr ubik connection */
129         pr_End();
130         if ((code == 0) && (viceId == ANONYMOUSID))
131             code = PRNOENT;
132         if (code) {
133             afs_com_err(whoami, code, "translating %s to id", username);
134             return 0;
135         }
136
137         sprintf(client.name, "AFS ID %d", viceId);
138         strcpy(client.instance, "");
139         strcpy(client.cell, server.cell);
140         code = ktc_SetToken(&server, &token, &client, /*dosetpag */ 0);
141         if (code)
142             return code;
143     }
144     return code;
145 }
146
147 #ifdef ka_UserAuthenticate
148 #undef ka_UserAuthenticate
149 #endif
150
151 afs_int32
152 ka_UserAuthenticateGeneral(afs_int32 flags, char *name, char *instance, 
153                            char *realm, char *password, Date lifetime, 
154                            afs_int32 * password_expires,        /* days 'til, or don't change if not set */
155                            afs_int32 spare2, char **reasonP)
156 {
157     int remainingTime = 0;
158     struct ktc_encryptionKey key;
159     afs_int32 code, dosetpag = 0;
160 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_USR_LINUX20_ENV) && !defined(AFS_XBSD_ENV) || defined(AFS_FBSD_ENV)
161     sig_t old;
162 #endif
163
164     if (reasonP)
165         *reasonP = "";
166     if ((flags & KA_USERAUTH_VERSION_MASK) != KA_USERAUTH_VERSION)
167         return KAOLDINTERFACE;
168     if ((strcmp(name, "root") == 0) && (instance == 0)) {
169         if (reasonP)
170             *reasonP = "root is only authenticated locally";
171         return KANOENT;
172     }
173     code = ka_Init(0);
174     if (code)
175         return code;
176
177     ka_StringToKey(password, realm, &key);
178
179 /* 
180  * alarm is set by klogin and kpasswd only so ignore for
181  * NT
182  */
183
184 #ifndef AFS_NT40_ENV
185     {                           /* Rx uses timers, save to be safe */
186         if (rx_socket) {
187             /* don't reset alarms, rx already running */
188             remainingTime = 0;
189         } else
190             remainingTime = alarm(0);
191     }
192 #endif
193
194 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_USR_LINUX20_ENV) && (!defined(AFS_XBSD_ENV) || defined(AFS_FBSD_ENV))
195     /* handle smoothly the case where no AFS system calls exists (yet) */
196     old = (int (*)())signal(SIGSYS, SIG_IGN);
197 #endif
198 #ifdef  AFS_DECOSF_ENV
199     (void)signal(SIGTRAP, SIG_IGN);
200 #endif /* AFS_DECOSF_ENV */
201     if (instance == 0)
202         instance = "";
203     if (flags & KA_USERAUTH_ONLY_VERIFY) {
204         code = ka_VerifyUserToken(name, instance, realm, &key);
205         if (code == KABADREQUEST) {
206             des_string_to_key(password, &key);
207             code = ka_VerifyUserToken(name, instance, realm, &key);
208         }
209     } else {
210 #ifdef AFS_DUX40_ENV
211         if (flags & KA_USERAUTH_DOSETPAG)
212             afs_setpag();
213 #else
214 #if !defined(UKERNEL) && !defined(AFS_NT40_ENV)
215         if (flags & KA_USERAUTH_DOSETPAG)
216             setpag();
217 #endif
218 #endif
219         if (flags & KA_USERAUTH_DOSETPAG2)
220             dosetpag = 1;
221 #ifdef AFS_KERBEROS_ENV
222         if ((flags & KA_USERAUTH_DOSETPAG) || dosetpag)
223             ktc_newpag();
224 #endif
225         if (lifetime == 0)
226             lifetime = MAXKTCTICKETLIFETIME;
227         code =
228             GetTickets(name, instance, realm, &key, lifetime,
229                        password_expires, dosetpag);
230         if (code == KABADREQUEST) {
231             des_string_to_key(password, &key);
232             code =
233                 GetTickets(name, instance, realm, &key, lifetime,
234                            password_expires, dosetpag);
235         }
236
237 /* By the time 3.3 comes out, these "old-style" passwd programs should be 
238  * well and truly obsolete.  Any passwords set with such a program
239  * OUGHT to have been changed years ago.  Having 2 -or- 3
240  * authentication RPCs generated for every klog plays hob with the
241  * "failed login limits" code in the kaserver, and it's hard to
242  * explain to admins just how to set the limit properly.  By removing 
243  * this function, we can just double it internally in the kaserver, and 
244  * not document anything.  kpasswd had the TRUNCATEPASSWORD "feature"
245  * disabled on 10/02/90.
246  */
247 #ifdef OLDCRUFT
248         if ((code == KABADREQUEST) && (strlen(password) > 8)) {
249             /* try with only the first 8 characters incase they set their password
250              * with an old style passwd program. */
251             char pass8[9];
252             strncpy(pass8, password, 8);
253             pass8[8] = 0;
254             ka_StringToKey(pass8, realm, &key);
255             memset(pass8, 0, sizeof(pass8));
256             code =
257                 GetTickets(name, instance, realm, &key, lifetime,
258                            password_expires, dosetpag);
259             if (code == 0) {
260                 fprintf(stderr, "%s %s\n%s %s\n%s\n",
261                         "Warning: you have typed a password longer than 8",
262                         "characters, but only the",
263                         "first 8 characters were actually significant.  If",
264                         "you change your password",
265                         "again this warning message will go away.\n");
266             }
267         }
268 #endif /* OLDCRUFT */
269     }
270
271 #ifndef AFS_NT40_ENV
272     if (remainingTime) {
273         pr_End();
274         rx_Finalize();
275         alarm(remainingTime);   /* restore timer, if any */
276     }
277 #endif
278
279     if (code && reasonP)
280         switch (code) {
281         case KABADREQUEST:
282             *reasonP = "password was incorrect";
283             break;
284         case KAUBIKCALL:
285             *reasonP = "Authentication Server was unavailable";
286             break;
287         default:
288             *reasonP = (char *)afs_error_message(code);
289         }
290     return code;
291 }
292
293 /* For backward compatibility */
294 afs_int32
295 ka_UserAuthenticate(char *name, char *instance, char *realm, char *password,
296                     int doSetPAG, char **reasonP)
297 {
298     return ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
299                                       ((doSetPAG) ? KA_USERAUTH_DOSETPAG : 0),
300                                       name, instance, realm, password,
301                                       /*lifetime */ 0, /*spare1,2 */ 0, 0,
302                                       reasonP);
303 }
304
305 #if !defined(UKERNEL)
306 afs_int32
307 ka_UserReadPassword(char *prompt, char *password, int plen, char **reasonP)
308 {
309     afs_int32 code = 0;
310
311     if (reasonP)
312         *reasonP = "";
313     code = ka_Init(0);
314     if (code)
315         return code;
316     code = read_pw_string(password, plen, prompt, 0);
317     if (code)
318         code = KAREADPW;
319     else if (strlen(password) == 0)
320         code = KANULLPASSWORD;
321     else
322         return 0;
323
324     if (reasonP) {
325         *reasonP = (char *)afs_error_message(code);
326     }
327     return code;
328 }
329 #endif /* !defined(UKERNEL) */
330
331 afs_int32
332 ka_VerifyUserPassword(afs_int32 version, char *name, char *instance,
333                       char *realm, char *password, int spare, char **reasonP)
334 {
335     afs_int32 pwexpires;
336
337     version &= KA_USERAUTH_VERSION_MASK;
338     return ka_UserAuthenticateGeneral(version | KA_USERAUTH_ONLY_VERIFY, name,
339                                       instance, realm, password, 0,
340                                       &pwexpires, spare, reasonP);
341 }