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