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