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