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