71521b0ab45b7f2395a6b693c06047c62eacfe6c
[openafs.git] / src / kauth / katoken.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 /* These routines provide an interface to the token cache maintained by the
11    kernel.  Principally it handles cache misses by requesting the desired token
12    from the AuthServer. */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16 #include <afs/stds.h>
17
18 #include <roken.h>
19
20 #ifdef UKERNEL
21 # include "afsincludes.h"
22 #endif
23
24 #include <rx/xdr.h>
25 #include <afs/pthread_glock.h>
26 #include <afs/cellconfig.h>
27 #include <afs/auth.h>
28 #include <lock.h>
29 #include <ubik.h>
30
31 #include "kauth.h"
32 #include "kautils.h"
33
34
35 afs_int32
36 ka_GetAuthToken(char *name, char *instance, char *cell,
37                 struct ktc_encryptionKey * key, afs_int32 lifetime,
38                 afs_int32 * pwexpires)
39 {
40     afs_int32 code;
41     struct ubik_client *conn;
42     afs_int32 now = time(0);
43     struct ktc_token token;
44     char cellname[MAXKTCREALMLEN];
45     char realm[MAXKTCREALMLEN];
46     struct ktc_principal client, server;
47
48     LOCK_GLOBAL_MUTEX;
49     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
50     if (code) {
51         UNLOCK_GLOBAL_MUTEX;
52         return code;
53     }
54     cell = cellname;
55
56     /* get an unauthenticated connection to desired cell */
57     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
58     if (code) {
59         UNLOCK_GLOBAL_MUTEX;
60         return code;
61     }
62     code =
63         ka_Authenticate(name, instance, cell, conn,
64                         KA_TICKET_GRANTING_SERVICE, key, now, now + lifetime,
65                         &token, pwexpires);
66     if (code) {
67         UNLOCK_GLOBAL_MUTEX;
68         return code;
69     }
70     code = ubik_ClientDestroy(conn);
71     if (code) {
72         UNLOCK_GLOBAL_MUTEX;
73         return code;
74     }
75
76     code = ka_CellToRealm(cell, realm, 0 /*local */ );
77     if (code) {
78         UNLOCK_GLOBAL_MUTEX;
79         return code;
80     }
81     strcpy(client.name, name);
82     strcpy(client.instance, instance);
83     strncpy(client.cell, cell, sizeof(client.cell));
84     strcpy(server.name, KA_TGS_NAME);
85     strcpy(server.instance, realm);
86     strcpy(server.cell, cell);
87     code = ktc_SetToken(&server, &token, &client, 0);
88     UNLOCK_GLOBAL_MUTEX;
89     return code;
90 }
91
92 afs_int32
93 ka_GetServerToken(char *name, char *instance, char *cell, Date lifetime,
94                   struct ktc_token * token, int new, int dosetpag)
95 {
96     afs_int32 code;
97     struct ubik_client *conn;
98     afs_int32 now = time(0);
99     struct ktc_token auth_token;
100     struct ktc_token cell_token;
101     struct ktc_principal server, auth_server, client;
102     char *localCell = ka_LocalCell();
103     char cellname[MAXKTCREALMLEN];
104     char realm[MAXKTCREALMLEN];
105     char authDomain[MAXKTCREALMLEN];
106     int local;
107
108     LOCK_GLOBAL_MUTEX;
109     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
110     if (code) {
111         UNLOCK_GLOBAL_MUTEX;
112         return code;
113     }
114     cell = cellname;
115
116     strcpy(server.name, name);
117     strcpy(server.instance, instance);
118     lcstring(server.cell, cell, sizeof(server.cell));
119     if (!new) {
120         code =
121             ktc_GetToken(&server, token, sizeof(struct ktc_token), &client);
122         if (!code) {
123             UNLOCK_GLOBAL_MUTEX;
124             return 0;
125         }
126     }
127
128     code = ka_CellToRealm(cell, realm, &local);
129     if (code) {
130         UNLOCK_GLOBAL_MUTEX;
131         return code;
132     }
133
134     /* get TGS ticket for proper realm */
135     strcpy(auth_server.name, KA_TGS_NAME);
136     strcpy(auth_server.instance, realm);
137     lcstring(auth_server.cell, realm, sizeof(auth_server.cell));
138     strcpy(authDomain, realm);
139     code =
140         ktc_GetToken(&auth_server, &auth_token, sizeof(auth_token), &client);
141     if (code && !local) {       /* try for remotely authenticated ticket */
142         strcpy(auth_server.cell, localCell);
143         strcpy(authDomain, "");
144         code =
145             ktc_GetToken(&auth_server, &auth_token, sizeof(auth_token),
146                          &client);
147     }
148
149     if (code && local) {
150         UNLOCK_GLOBAL_MUTEX;
151         return code;
152     } else if (code) {
153         /* here we invoke the inter-cell mechanism */
154
155         /* get local auth ticket */
156         ucstring(auth_server.instance, localCell,
157                  sizeof(auth_server.instance));
158         strcpy(auth_server.cell, localCell);
159         code =
160             ktc_GetToken(&auth_server, &cell_token, sizeof(cell_token),
161                          &client);
162         if (code) {
163             UNLOCK_GLOBAL_MUTEX;
164             return code;
165         }
166         /* get a connection to the local cell */
167         if ((code =
168              ka_AuthServerConn(localCell, KA_TICKET_GRANTING_SERVICE, 0,
169                                &conn))) {
170             UNLOCK_GLOBAL_MUTEX;
171             return code;
172         }
173         /* get foreign auth ticket */
174         if ((code =
175              ka_GetToken(KA_TGS_NAME, realm, localCell, client.name,
176                          client.instance, conn, now, now + lifetime,
177                          &cell_token, "" /* local auth domain */ ,
178                          &auth_token))) {
179             UNLOCK_GLOBAL_MUTEX;
180             return code;
181         }
182         code = ubik_ClientDestroy(conn);
183         if (code) {
184             UNLOCK_GLOBAL_MUTEX;
185             return code;
186         }
187         conn = 0;
188
189         /* save foreign auth ticket */
190         strcpy(auth_server.instance, realm);
191         lcstring(auth_server.cell, localCell, sizeof(auth_server.cell));
192         ucstring(authDomain, localCell, sizeof(authDomain));
193         if ((code = ktc_SetToken(&auth_server, &auth_token, &client, 0))) {
194             UNLOCK_GLOBAL_MUTEX;
195             return code;
196         }
197     }
198
199     if ((code =
200          ka_AuthServerConn(cell, KA_TICKET_GRANTING_SERVICE, 0, &conn))) {
201         UNLOCK_GLOBAL_MUTEX;
202         return code;
203     }
204     if ((code =
205          ka_GetToken(name, instance, cell, client.name, client.instance, conn,
206                      now, now + lifetime, &auth_token, authDomain, token))) {
207         UNLOCK_GLOBAL_MUTEX;
208         return code;
209     }
210     code = ubik_ClientDestroy(conn);
211     if (code) {
212         UNLOCK_GLOBAL_MUTEX;
213         return code;
214     }
215
216     if ((code =
217          ktc_SetToken(&server, token, &client,
218                       dosetpag ? AFS_SETTOK_SETPAG : 0))) {
219         UNLOCK_GLOBAL_MUTEX;
220         return code;
221     }
222     UNLOCK_GLOBAL_MUTEX;
223     return 0;
224 }
225
226 afs_int32
227 ka_GetAdminToken(char *name, char *instance, char *cell,
228                  struct ktc_encryptionKey * key, afs_int32 lifetime,
229                  struct ktc_token * token, int new)
230 {
231     int code;
232     struct ubik_client *conn;
233     afs_int32 now = time(0);
234     struct ktc_principal server, client;
235     struct ktc_token localToken;
236     char cellname[MAXKTCREALMLEN];
237
238     LOCK_GLOBAL_MUTEX;
239     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
240     if (code) {
241         UNLOCK_GLOBAL_MUTEX;
242         return code;
243     }
244     cell = cellname;
245
246     if (token == 0)
247         token = &localToken;    /* in case caller doesn't want token */
248
249     strcpy(server.name, KA_ADMIN_NAME);
250     strcpy(server.instance, KA_ADMIN_INST);
251     strncpy(server.cell, cell, sizeof(server.cell));
252     if (!new) {
253         code =
254             ktc_GetToken(&server, token, sizeof(struct ktc_token), &client);
255         if (code == 0) {
256             UNLOCK_GLOBAL_MUTEX;
257             return 0;
258         }
259     }
260
261     if ((name == 0) || (key == 0)) {
262         /* just lookup in cache don't get new one */
263         UNLOCK_GLOBAL_MUTEX;
264         return KANOTICKET;
265     }
266
267     /* get an unauthenticated connection to desired cell */
268     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
269     if (code) {
270         UNLOCK_GLOBAL_MUTEX;
271         return code;
272     }
273     code =
274         ka_Authenticate(name, instance, cell, conn, KA_MAINTENANCE_SERVICE,
275                         key, now, now + lifetime, token, 0);
276     (void)ubik_ClientDestroy(conn);
277     if (code) {
278         UNLOCK_GLOBAL_MUTEX;
279         return code;
280     }
281
282     strcpy(client.name, name);
283     strcpy(client.instance, instance);
284     strncpy(client.cell, cell, sizeof(client.cell));
285     code = ktc_SetToken(&server, token, &client, 0);
286     UNLOCK_GLOBAL_MUTEX;
287     return code;
288 }
289
290
291 afs_int32
292 ka_VerifyUserToken(char *name, char *instance, char *cell,
293                    struct ktc_encryptionKey * key)
294 {
295     afs_int32 code;
296     struct ubik_client *conn;
297     afs_int32 now = time(0);
298     struct ktc_token token;
299     char cellname[MAXKTCREALMLEN];
300     afs_int32 pwexpires;
301
302     LOCK_GLOBAL_MUTEX;
303     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
304     if (code) {
305         UNLOCK_GLOBAL_MUTEX;
306         return code;
307     }
308
309     cell = cellname;
310
311     /* get an unauthenticated connection to desired cell */
312     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
313     if (code) {
314         UNLOCK_GLOBAL_MUTEX;
315         return code;
316     }
317
318     code =
319         ka_Authenticate(name, instance, cell, conn,
320                         KA_TICKET_GRANTING_SERVICE, key, now,
321                         now + MAXKTCTICKETLIFETIME, &token, &pwexpires);
322     if (code) {
323         UNLOCK_GLOBAL_MUTEX;
324         return code;
325     }
326     code = ubik_ClientDestroy(conn);
327     UNLOCK_GLOBAL_MUTEX;
328     return code;
329 }