Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / kauth / authclient.c
blob0d577714eccd2547926cd5a751e9688c61acd64c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
10 /* These routines provide a convenient interface to the AuthServer. */
12 #include <afsconfig.h>
13 #include <afs/param.h>
15 #ifdef IGNORE_SOME_GCC_WARNINGS
16 # pragma GCC diagnostic warning "-Wstrict-prototypes"
17 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
18 #endif
20 #define UBIK_LEGACY_CALLITER 1
22 #include <afs/stds.h>
23 #include <afs/pthread_glock.h>
24 #include <sys/types.h>
25 #ifdef AFS_NT40_ENV
26 #include <winsock2.h>
27 #else
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #endif
31 #ifdef HAVE_STDINT_H
32 # include <stdint.h>
33 #endif
34 #include <string.h>
35 #include <stdio.h>
36 #include <des.h>
37 #include <des_prototypes.h>
38 #include <rx/rxkad.h>
39 #include <afs/cellconfig.h>
40 #include <ubik.h>
41 #include <afs/auth.h>
42 #include <afs/afsutil.h>
43 #include "kauth.h"
44 #include "kautils.h"
46 #ifdef UKERNEL
47 #include "afs_usrops.h"
48 #endif
50 static struct afsconf_dir *conf = 0;
51 static struct afsconf_cell explicit_cell_server_list;
52 static struct afsconf_cell debug_cell_server_list;
53 static int explicit = 0;
54 static int debug = 0;
56 #ifdef ENCRYPTIONBLOCKSIZE
57 #undef ENCRYPTIONBLOCKSIZE
58 #endif
59 #define ENCRYPTIONBLOCKSIZE (sizeof(des_cblock))
61 /* Copy the specified list of servers into a specially know cell named
62 "explicit". The cell can then be used to debug experimental servers. */
64 void
65 ka_ExplicitCell(char *cell, afs_uint32 serverList[])
67 int i;
69 LOCK_GLOBAL_MUTEX;
70 ka_ExpandCell(cell, explicit_cell_server_list.name, 0);
71 for (i = 0; i < MAXHOSTSPERCELL; i++)
72 if (serverList[i]) {
73 explicit_cell_server_list.numServers = i + 1;
74 explicit_cell_server_list.hostAddr[i].sin_family = AF_INET;
75 explicit_cell_server_list.hostAddr[i].sin_addr.s_addr =
76 serverList[i];
77 explicit_cell_server_list.hostName[i][0] = 0;
78 explicit_cell_server_list.hostAddr[i].sin_port =
79 htons(AFSCONF_KAUTHPORT);
80 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
81 explicit_cell_server_list.hostAddr[i].sin_len =
82 sizeof(struct sockaddr_in);
83 #endif
84 explicit = 1;
85 } else
86 break;
87 UNLOCK_GLOBAL_MUTEX;
90 static int
91 myCellLookup(struct afsconf_dir *conf, char *cell, char *service,
92 struct afsconf_cell *cellinfo)
94 if (debug) {
95 *cellinfo = debug_cell_server_list;
96 return 0;
97 } else if (explicit
98 && (strcmp(cell, explicit_cell_server_list.name) == 0)) {
99 *cellinfo = explicit_cell_server_list;
100 return 0;
102 /* call the real one */
103 else
104 return afsconf_GetCellInfo(conf, cell, service, cellinfo);
107 afs_int32
108 ka_GetServers(char *cell, struct afsconf_cell * cellinfo)
110 afs_int32 code;
111 char cellname[MAXKTCREALMLEN];
113 LOCK_GLOBAL_MUTEX;
114 if (cell && !strlen(cell))
115 cell = 0;
116 else
117 cell = lcstring(cellname, cell, sizeof(cellname));
119 if (!conf) {
120 #ifdef UKERNEL
121 conf = afs_cdir;
122 #else /* UKERNEL */
123 conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
124 #endif /* UKERNEL */
125 if (!conf) {
126 UNLOCK_GLOBAL_MUTEX;
127 return KANOCELLS;
130 code = myCellLookup(conf, cell, AFSCONF_KAUTHSERVICE, cellinfo);
131 UNLOCK_GLOBAL_MUTEX;
132 return code;
135 afs_int32
136 ka_GetSecurity(int service, struct ktc_token * token,
137 struct rx_securityClass ** scP, int *siP)
138 { /* security class index */
139 LOCK_GLOBAL_MUTEX;
140 *scP = 0;
141 switch (service) {
142 case KA_AUTHENTICATION_SERVICE:
143 case KA_TICKET_GRANTING_SERVICE:
144 no_security:
145 *scP = rxnull_NewClientSecurityObject();
146 *siP = RX_SCINDEX_NULL;
147 break;
148 case KA_MAINTENANCE_SERVICE:
149 if (!token)
150 goto no_security;
151 *scP =
152 rxkad_NewClientSecurityObject(rxkad_crypt, &token->sessionKey,
153 token->kvno, token->ticketLen,
154 token->ticket);
155 *siP = RX_SCINDEX_KAD;
156 break;
157 default:
158 UNLOCK_GLOBAL_MUTEX;
159 return KABADARGUMENT;
161 if (*scP == 0) {
162 printf("Failed gettting security object\n");
163 UNLOCK_GLOBAL_MUTEX;
164 return KARXFAIL;
166 UNLOCK_GLOBAL_MUTEX;
167 return 0;
170 afs_int32
171 ka_SingleServerConn(char *cell, char *server, /* name of server to contact */
172 int service, struct ktc_token * token,
173 struct ubik_client ** conn)
175 afs_int32 code;
176 struct rx_connection *serverconns[2];
177 struct rx_securityClass *sc;
178 int si; /* security class index */
179 struct afsconf_cell cellinfo; /* for cell auth server list */
180 int i;
181 int match;
182 char sname[MAXHOSTCHARS];
183 int snamel;
185 LOCK_GLOBAL_MUTEX;
186 code = ka_GetServers(cell, &cellinfo);
187 if (code) {
188 UNLOCK_GLOBAL_MUTEX;
189 return code;
192 lcstring(sname, server, sizeof(sname));
193 snamel = strlen(sname);
194 match = -1;
195 for (i = 0; i < cellinfo.numServers; i++) {
196 if (strncmp(cellinfo.hostName[i], sname, snamel) == 0) {
197 if (match >= 0) {
198 UNLOCK_GLOBAL_MUTEX;
199 return KANOCELLS;
200 } else
201 match = i;
204 if (match < 0) {
205 UNLOCK_GLOBAL_MUTEX;
206 return KANOCELLS;
209 code = rx_Init(0);
210 if (code) {
211 UNLOCK_GLOBAL_MUTEX;
212 return code;
215 code = ka_GetSecurity(service, token, &sc, &si);
216 if (code) {
217 UNLOCK_GLOBAL_MUTEX;
218 return code;
220 #ifdef AFS_PTHREAD_ENV
221 serverconns[0] =
222 rx_GetCachedConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
223 cellinfo.hostAddr[match].sin_port, service, sc,
224 si);
225 #else
226 serverconns[0] =
227 rx_NewConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
228 cellinfo.hostAddr[match].sin_port, service, sc, si);
229 #endif
230 serverconns[1] = 0; /* terminate list */
232 /* next, pass list of server rx_connections (in serverconns), and a place
233 * to put the returned client structure that we'll use in all of our rpc
234 * calls (via ubik_Call) */
235 *conn = 0;
236 code = ubik_ClientInit(serverconns, conn);
237 rxs_Release(sc);
238 UNLOCK_GLOBAL_MUTEX;
239 if (code)
240 return KAUBIKINIT;
241 return 0;
244 afs_int32
245 ka_AuthSpecificServersConn(int service, struct ktc_token * token,
246 struct afsconf_cell * cellinfo,
247 struct ubik_client ** conn)
249 afs_int32 code;
250 struct rx_connection *serverconns[MAXSERVERS];
251 struct rx_securityClass *sc;
252 int si; /* security class index */
253 int i;
255 LOCK_GLOBAL_MUTEX;
256 code = rx_Init(0);
257 if (code) {
258 UNLOCK_GLOBAL_MUTEX;
259 return code;
262 code = ka_GetSecurity(service, token, &sc, &si);
263 if (code) {
264 UNLOCK_GLOBAL_MUTEX;
265 return code;
268 for (i = 0; i < cellinfo->numServers; i++)
269 #ifdef AFS_PTHREAD_ENV
270 serverconns[i] =
271 rx_GetCachedConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
272 cellinfo->hostAddr[i].sin_port, service,
273 sc, si);
274 #else
275 serverconns[i] =
276 rx_NewConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
277 cellinfo->hostAddr[i].sin_port, service, sc, si);
278 #endif
279 serverconns[cellinfo->numServers] = 0; /* terminate list */
281 /* next, pass list of server rx_connections (in serverconns), and a place
282 * to put the returned client structure that we'll use in all of our rpc
283 * calls (via ubik_Call) */
284 *conn = 0;
285 code = ubik_ClientInit(serverconns, conn);
286 rxs_Release(sc);
287 UNLOCK_GLOBAL_MUTEX;
288 if (code)
289 return KAUBIKINIT;
290 return 0;
293 afs_int32
294 ka_AuthServerConn(char *cell, int service, struct ktc_token * token,
295 struct ubik_client ** conn)
297 afs_int32 code;
298 struct rx_connection *serverconns[MAXSERVERS];
299 struct rx_securityClass *sc;
300 int si; /* security class index */
301 int i;
302 struct afsconf_cell cellinfo; /* for cell auth server list */
304 LOCK_GLOBAL_MUTEX;
305 code = ka_GetServers(cell, &cellinfo);
306 if (code) {
307 UNLOCK_GLOBAL_MUTEX;
308 return code;
311 code = rx_Init(0);
312 if (code) {
313 UNLOCK_GLOBAL_MUTEX;
314 return code;
317 code = ka_GetSecurity(service, token, &sc, &si);
318 if (code) {
319 UNLOCK_GLOBAL_MUTEX;
320 return code;
323 for (i = 0; i < cellinfo.numServers; i++)
324 #ifdef AFS_PTHREAD_ENV
325 serverconns[i] =
326 rx_GetCachedConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
327 cellinfo.hostAddr[i].sin_port, service, sc,
328 si);
329 #else
330 serverconns[i] =
331 rx_NewConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
332 cellinfo.hostAddr[i].sin_port, service, sc, si);
333 #endif
334 serverconns[cellinfo.numServers] = 0; /* terminate list */
336 /* next, pass list of server rx_connections (in serverconns), and a place
337 * to put the returned client structure that we'll use in all of our rpc
338 * calls (via ubik_Call) */
339 *conn = 0;
340 code = ubik_ClientInit(serverconns, conn);
341 rxs_Release(sc);
342 UNLOCK_GLOBAL_MUTEX;
343 if (code)
344 return KAUBIKINIT;
345 return 0;
348 static afs_int32
349 CheckTicketAnswer(ka_BBS * oanswer, afs_int32 challenge,
350 struct ktc_token *token, struct ktc_principal *caller,
351 struct ktc_principal *server, char *label,
352 afs_int32 * pwexpires)
354 struct ka_ticketAnswer *answer;
355 unsigned char tempc;
357 answer = (struct ka_ticketAnswer *)oanswer->SeqBody;
359 if (challenge != ntohl(answer->challenge))
360 return KABADPROTOCOL;
361 memcpy(&token->sessionKey, &answer->sessionKey,
362 sizeof(token->sessionKey));
363 token->startTime = ntohl(answer->startTime);
364 token->endTime = ntohl(answer->endTime);
365 token->kvno = (short)ntohl(answer->kvno);
366 token->ticketLen = ntohl(answer->ticketLen);
368 if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0)
369 return KABADPROTOCOL;
370 if ((token->ticketLen < MINKTCTICKETLEN)
371 || (token->ticketLen > MAXKTCTICKETLEN))
372 return KABADPROTOCOL;
375 char *strings = answer->name;
376 int len;
377 #undef chkstr
378 #define chkstr(field) \
379 len = strlen (strings); \
380 if (len > MAXKTCNAMELEN) return KABADPROTOCOL;\
381 if ((field) && strcmp (field, strings)) return KABADPROTOCOL;\
382 strings += len+1
384 #define chknostr() \
385 len = strlen(strings); \
386 if (len > MAXKTCNAMELEN) return KABADPROTOCOL; \
387 strings += len+1
389 if (caller) {
390 chkstr(caller->name);
391 chkstr(caller->instance);
392 chkstr(caller->cell);
393 } else {
394 chknostr();
395 chknostr();
396 chknostr();
398 if (server) {
399 chkstr(server->name);
400 chkstr(server->instance);
401 } else {
402 chknostr();
403 chknostr();
406 if (oanswer->SeqLen -
407 ((strings - oanswer->SeqBody) + token->ticketLen + KA_LABELSIZE)
408 >= (ENCRYPTIONBLOCKSIZE + 12)
410 return KABADPROTOCOL;
412 memcpy(token->ticket, strings, token->ticketLen);
413 strings += token->ticketLen;
414 if (memcmp(strings, label, KA_LABELSIZE) != 0)
415 return KABADPROTOCOL;
417 if (pwexpires) {
418 afs_int32 temp;
419 strings += KA_LABELSIZE;
420 temp = round_up_to_ebs((strings - oanswer->SeqBody));
422 if (oanswer->SeqLen > temp) {
423 strings = oanswer->SeqBody + temp;
424 memcpy(&temp, strings, sizeof(afs_int32));
425 tempc = ntohl(temp) >> 24;
426 /* don't forget this if you add any more fields!
427 * strings += sizeof(afs_int32);
429 } else {
430 tempc = 255;
432 *pwexpires = tempc;
436 return 0;
439 /* call this instead of stub and we'll guarantee to find a host that's up.
440 * this doesn't handle UNOTSYNC very well, should use ubik_Call if you care
442 static afs_int32
443 kawrap_ubik_Call(int (*aproc) (), struct ubik_client *aclient,
444 afs_int32 aflags, void *p1, void *p2, void *p3, void *p4,
445 void *p5, void *p6, void *p7, void *p8)
447 afs_int32 code, lcode;
448 int count;
449 int pass;
451 /* First pass only checks servers known running. Second checks all.
452 * Once we've cycled through all the servers and still nothing, return
453 * error code from the last server tried.
455 for (pass = 0, aflags |= UPUBIKONLY; pass < 2;
456 pass++, aflags &= ~UPUBIKONLY) {
457 code = 0;
458 count = 0;
459 do { /* Cycle through the servers */
460 lcode = code;
461 code =
462 ubik_CallIter(aproc, aclient, aflags, &count, (long) p1,
463 (long) p2, (long) p3, (long) p4,
464 (long) p5, (long) p6, (long) p7,
465 (long) p8, 0, 0, 0, 0, 0, 0, 0, 0);
466 } while ((code == UNOQUORUM) || (code == UNOTSYNC)
467 || (code == KALOCKED) || (code == -1));
469 if (code != UNOSERVERS)
470 break;
473 /* If cycled through all the servers, return the last error code */
474 if ((code == UNOSERVERS) && lcode) {
475 code = lcode;
477 return code;
480 /* This is the interface to the AuthServer RPC routine Authenticate. It
481 formats the request packet, calls the encryption routine on the answer,
482 calls Authenticate, and decrypts the response. The response is checked for
483 correctness and its contents are copied into the token. */
485 /* Errors:
486 KABADKEY = the key failed when converted to a key schedule. Probably bad
487 parity.
488 KAUBIKCALL - the call to Ubik returned an error, probably a communication
489 failure such as timeout.
490 KABADPROTOCOL - the returned packet was in error. Since a packet was
491 returned it can be presumed that the AuthServer correctly interpreted
492 the response. This may indicate an inauthentic AuthServer.
493 <other> - errors generated by the server process are returned directly.
496 afs_int32
497 ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * conn, /* Ubik connection to the AuthServer in
498 * the desired cell */
499 int service, /* ticket granting or admin service */
500 struct ktc_encryptionKey * key, Date start, Date end, /* ticket lifetime */
501 struct ktc_token * token, afs_int32 * pwexpires)
502 { /* days until it expires */
503 afs_int32 code;
504 des_key_schedule schedule;
505 Date request_time;
506 struct ka_gettgtRequest request;
507 struct ka_gettgtAnswer answer_old;
508 struct ka_ticketAnswer answer;
509 ka_CBS arequest;
510 ka_BBS oanswer;
511 char *req_label;
512 char *ans_label;
513 int version;
515 LOCK_GLOBAL_MUTEX;
516 if ((code = des_key_sched(ktc_to_cblock(key), schedule))) {
517 UNLOCK_GLOBAL_MUTEX;
518 return KABADKEY;
521 if (service == KA_MAINTENANCE_SERVICE) {
522 req_label = KA_GETADM_REQ_LABEL;
523 ans_label = KA_GETADM_ANS_LABEL;
524 } else if (service == KA_TICKET_GRANTING_SERVICE) {
525 req_label = KA_GETTGT_REQ_LABEL;
526 ans_label = KA_GETTGT_ANS_LABEL;
527 } else {
528 UNLOCK_GLOBAL_MUTEX;
529 return KABADARGUMENT;
532 request_time = time(0);
533 request.time = htonl(request_time);
534 memcpy(request.label, req_label, sizeof(request.label));
535 arequest.SeqLen = sizeof(request);
536 arequest.SeqBody = (char *)&request;
537 des_pcbc_encrypt(arequest.SeqBody, arequest.SeqBody, arequest.SeqLen,
538 schedule, ktc_to_cblockptr(key), ENCRYPT);
540 oanswer.MaxSeqLen = sizeof(answer);
541 oanswer.SeqLen = 0;
542 oanswer.SeqBody = (char *)&answer;
544 version = 2;
545 code =
546 kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
547 (void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
548 if (code == RXGEN_OPCODE) {
549 oanswer.MaxSeqLen = sizeof(answer);
550 oanswer.SeqBody = (char *)&answer;
551 version = 1;
552 code =
553 ubik_KAA_Authenticate(conn, 0, name, instance, start, end,
554 &arequest, &oanswer);
555 if (code == RXGEN_OPCODE) {
556 oanswer.MaxSeqLen = sizeof(answer_old);
557 oanswer.SeqBody = (char *)&answer_old;
558 version = 0;
559 code =
560 ubik_KAA_Authenticate_old(conn, 0, name, instance,
561 start, end, &arequest, &oanswer);
563 if (code == RXGEN_OPCODE) {
564 code = KAOLDINTERFACE;
567 if (code) {
568 UNLOCK_GLOBAL_MUTEX;
569 if ((code >= KAMINERROR) && (code <= KAMAXERROR))
570 return code;
571 return KAUBIKCALL;
573 des_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
574 schedule, ktc_to_cblockptr(key), DECRYPT);
576 switch (version) {
577 case 1:
578 case 2:
580 struct ktc_principal caller;
581 strcpy(caller.name, name);
582 strcpy(caller.instance, instance);
583 strcpy(caller.cell, "");
584 code =
585 CheckTicketAnswer(&oanswer, request_time + 1, token, &caller,
586 0, ans_label, pwexpires);
587 if (code) {
588 UNLOCK_GLOBAL_MUTEX;
589 return code;
592 break;
593 case 0:
594 answer_old.time = ntohl(answer_old.time);
595 answer_old.ticket_len = ntohl(answer_old.ticket_len);
596 if ((answer_old.time != request_time + 1)
597 || (answer_old.ticket_len < MINKTCTICKETLEN)
598 || (answer_old.ticket_len > MAXKTCTICKETLEN)) {
599 UNLOCK_GLOBAL_MUTEX;
600 return KABADPROTOCOL;
603 char *label = ((char *)answer_old.ticket) + answer_old.ticket_len;
605 if (strncmp(label, ans_label, sizeof(answer_old.label))) {
606 UNLOCK_GLOBAL_MUTEX;
607 return KABADPROTOCOL;
609 token->startTime = start;
610 token->endTime = end;
611 token->kvno = ntohl(answer_old.kvno);
612 token->ticketLen = answer_old.ticket_len;
613 memcpy(token->ticket, answer_old.ticket, sizeof(token->ticket));
614 memcpy(&token->sessionKey, &answer_old.sessionkey,
615 sizeof(struct ktc_encryptionKey));
617 break;
618 default:
619 UNLOCK_GLOBAL_MUTEX;
620 return KAINTERNALERROR;
623 UNLOCK_GLOBAL_MUTEX;
624 return 0;
627 afs_int32
628 ka_GetToken(char *name, char *instance, char *cell, char *cname, char *cinst, struct ubik_client * conn, /* Ubik conn to cell's AuthServer */
629 Date start, Date end, /* desired ticket lifetime */
630 struct ktc_token * auth_token, char *auth_domain,
631 struct ktc_token * token)
633 struct ka_getTicketTimes times;
634 struct ka_getTicketAnswer answer_old;
635 struct ka_ticketAnswer answer;
636 afs_int32 code;
637 ka_CBS aticket;
638 ka_CBS atimes;
639 ka_BBS oanswer;
640 char *strings;
641 int len;
642 des_key_schedule schedule;
643 int version;
644 afs_int32 pwexpires;
646 LOCK_GLOBAL_MUTEX;
647 aticket.SeqLen = auth_token->ticketLen;
648 aticket.SeqBody = auth_token->ticket;
650 code = des_key_sched(ktc_to_cblock(&auth_token->sessionKey), schedule);
651 if (code) {
652 UNLOCK_GLOBAL_MUTEX;
653 return KABADKEY;
656 times.start = htonl(start);
657 times.end = htonl(end);
658 des_ecb_encrypt(&times, &times, schedule, ENCRYPT);
660 atimes.SeqLen = sizeof(times);
661 atimes.SeqBody = (char *)&times;
663 oanswer.SeqLen = 0;
664 oanswer.MaxSeqLen = sizeof(answer);
665 oanswer.SeqBody = (char *)&answer;
667 version = 1;
668 code =
669 ubik_KAT_GetTicket(conn, 0, auth_token->kvno, auth_domain,
670 &aticket, name, instance, &atimes, &oanswer);
671 if (code == RXGEN_OPCODE) {
672 oanswer.SeqLen = 0; /* this may be set by first call */
673 oanswer.MaxSeqLen = sizeof(answer_old);
674 oanswer.SeqBody = (char *)&answer_old;
675 version = 0;
676 code =
677 ubik_KAT_GetTicket_old(conn, 0, auth_token->kvno,
678 auth_domain, &aticket, name, instance, &atimes,
679 &oanswer);
680 if (code == RXGEN_OPCODE) {
681 code = KAOLDINTERFACE;
684 if (code) {
685 UNLOCK_GLOBAL_MUTEX;
686 if ((code >= KAMINERROR) && (code <= KAMAXERROR))
687 return code;
688 return KAUBIKCALL;
691 des_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
692 schedule, ktc_to_cblockptr(&auth_token->sessionKey), DECRYPT);
694 switch (version) {
695 case 1:
697 struct ktc_principal server;
698 strcpy(server.name, name);
699 strcpy(server.instance, instance);
700 code =
701 CheckTicketAnswer(&oanswer, 0, token, 0, &server,
702 KA_GETTICKET_ANS_LABEL, &pwexpires);
703 if (code) {
704 UNLOCK_GLOBAL_MUTEX;
705 return code;
708 break;
709 case 0:
710 token->startTime = ntohl(answer_old.startTime);
711 token->endTime = ntohl(answer_old.endTime);
712 token->ticketLen = ntohl(answer_old.ticketLen);
713 token->kvno = ntohl(answer_old.kvno);
714 memcpy(&token->sessionKey, &answer_old.sessionKey,
715 sizeof(token->sessionKey));
717 if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0) {
718 UNLOCK_GLOBAL_MUTEX;
719 return KABADPROTOCOL;
721 if ((token->ticketLen < MINKTCTICKETLEN)
722 || (token->ticketLen > MAXKTCTICKETLEN)) {
723 UNLOCK_GLOBAL_MUTEX;
724 return KABADPROTOCOL;
726 strings = answer_old.name;
727 len = strlen(strings); /* check client name */
728 if ((len < 1) || (len > MAXKTCNAMELEN)) {
729 UNLOCK_GLOBAL_MUTEX;
730 return KABADPROTOCOL;
732 strings += len + 1; /* check client instance */
733 len = strlen(strings);
734 if ((len < 0) || (len > MAXKTCNAMELEN)) {
735 UNLOCK_GLOBAL_MUTEX;
736 return KABADPROTOCOL;
738 strings += len + 1;
739 len = strlen(strings); /* check client cell */
740 if ((len < 0) || (len > MAXKTCNAMELEN)) {
741 UNLOCK_GLOBAL_MUTEX;
742 return KABADPROTOCOL;
744 strings += len + 1;
745 len = strlen(strings); /* check server name */
746 if ((len < 1) || (len > MAXKTCNAMELEN) || strcmp(name, strings)) {
747 UNLOCK_GLOBAL_MUTEX;
748 return KABADPROTOCOL;
750 strings += len + 1;
751 len = strlen(strings); /* check server instance */
752 if ((len < 0) || (len > MAXKTCNAMELEN) || strcmp(instance, strings)) {
753 UNLOCK_GLOBAL_MUTEX;
754 return KABADPROTOCOL;
756 strings += len + 1;
758 if ((strings - oanswer.SeqBody + token->ticketLen) - oanswer.SeqLen >=
759 ENCRYPTIONBLOCKSIZE) {
760 UNLOCK_GLOBAL_MUTEX;
761 return KABADPROTOCOL;
763 memcpy(token->ticket, strings, token->ticketLen);
765 break;
766 default:
767 UNLOCK_GLOBAL_MUTEX;
768 return KAINTERNALERROR;
771 UNLOCK_GLOBAL_MUTEX;
772 return 0;
775 afs_int32
776 ka_ChangePassword(char *name, char *instance, struct ubik_client * conn, /* Ubik connection to the AuthServer in
777 * the desired cell */
778 struct ktc_encryptionKey * oldkey,
779 struct ktc_encryptionKey * newkey)
781 afs_int32 code;
783 LOCK_GLOBAL_MUTEX;
784 code =
785 ubik_KAM_SetPassword(conn, UBIK_CALL_NEW, name, instance, 0, *(EncryptionKey *)newkey);
786 UNLOCK_GLOBAL_MUTEX;
787 return code;