Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / kauth / authclient.c
blob4db0cbc1343dccfcc826f319755cd51fab1d0217
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>
14 #include <afs/stds.h>
16 #include <roken.h>
17 #include <afs/opr.h>
19 #ifdef IGNORE_SOME_GCC_WARNINGS
20 # pragma GCC diagnostic warning "-Wstrict-prototypes"
21 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
22 #endif
24 #include <hcrypto/des.h>
26 #define UBIK_LEGACY_CALLITER 1
28 #include <afs/pthread_glock.h>
29 #include <rx/rxkad.h>
30 #include <rx/rxkad_convert.h>
31 #include <afs/cellconfig.h>
32 #include <ubik.h>
33 #include <afs/auth.h>
34 #include <afs/afsutil.h>
36 #include "kauth.h"
37 #include "kautils.h"
39 static struct afsconf_dir *conf = 0;
40 static struct afsconf_cell explicit_cell_server_list;
41 static struct afsconf_cell debug_cell_server_list;
42 static int explicit = 0;
43 static int debug = 0;
45 #ifdef ENCRYPTIONBLOCKSIZE
46 #undef ENCRYPTIONBLOCKSIZE
47 #endif
48 #define ENCRYPTIONBLOCKSIZE (sizeof(DES_cblock))
50 /* Copy the specified list of servers into a specially know cell named
51 "explicit". The cell can then be used to debug experimental servers. */
53 void
54 ka_ExplicitCell(char *cell, afs_uint32 serverList[])
56 int i;
58 LOCK_GLOBAL_MUTEX;
59 ka_ExpandCell(cell, explicit_cell_server_list.name, 0);
60 for (i = 0; i < MAXHOSTSPERCELL; i++)
61 if (serverList[i]) {
62 explicit_cell_server_list.numServers = i + 1;
63 explicit_cell_server_list.hostAddr[i].sin_family = AF_INET;
64 explicit_cell_server_list.hostAddr[i].sin_addr.s_addr =
65 serverList[i];
66 explicit_cell_server_list.hostName[i][0] = 0;
67 explicit_cell_server_list.hostAddr[i].sin_port =
68 htons(AFSCONF_KAUTHPORT);
69 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
70 explicit_cell_server_list.hostAddr[i].sin_len =
71 sizeof(struct sockaddr_in);
72 #endif
73 explicit = 1;
74 } else
75 break;
76 UNLOCK_GLOBAL_MUTEX;
79 static int
80 myCellLookup(struct afsconf_dir *conf, char *cell, char *service,
81 struct afsconf_cell *cellinfo)
83 if (debug) {
84 *cellinfo = debug_cell_server_list;
85 return 0;
86 } else if (explicit
87 && (strcmp(cell, explicit_cell_server_list.name) == 0)) {
88 *cellinfo = explicit_cell_server_list;
89 return 0;
91 /* call the real one */
92 else
93 return afsconf_GetCellInfo(conf, cell, service, cellinfo);
96 afs_int32
97 ka_GetServers(char *cell, struct afsconf_cell * cellinfo)
99 afs_int32 code;
100 char cellname[MAXKTCREALMLEN];
102 LOCK_GLOBAL_MUTEX;
103 if (cell == NULL || strlen(cell) == 0)
104 cell = NULL;
105 else
106 cell = lcstring(cellname, cell, sizeof(cellname));
108 if (!conf) {
109 conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
110 if (!conf) {
111 UNLOCK_GLOBAL_MUTEX;
112 return KANOCELLS;
115 code = myCellLookup(conf, cell, AFSCONF_KAUTHSERVICE, cellinfo);
116 UNLOCK_GLOBAL_MUTEX;
117 return code;
120 afs_int32
121 ka_GetSecurity(int service, struct ktc_token * token,
122 struct rx_securityClass ** scP, int *siP)
123 { /* security class index */
124 LOCK_GLOBAL_MUTEX;
125 *scP = 0;
126 switch (service) {
127 case KA_AUTHENTICATION_SERVICE:
128 case KA_TICKET_GRANTING_SERVICE:
129 no_security:
130 *scP = rxnull_NewClientSecurityObject();
131 *siP = RX_SECIDX_NULL;
132 break;
133 case KA_MAINTENANCE_SERVICE:
134 if (!token)
135 goto no_security;
136 *scP =
137 rxkad_NewClientSecurityObject(rxkad_crypt, &token->sessionKey,
138 token->kvno, token->ticketLen,
139 token->ticket);
140 *siP = RX_SECIDX_KAD;
141 break;
142 default:
143 UNLOCK_GLOBAL_MUTEX;
144 return KABADARGUMENT;
146 if (*scP == 0) {
147 printf("Failed gettting security object\n");
148 UNLOCK_GLOBAL_MUTEX;
149 return KARXFAIL;
151 UNLOCK_GLOBAL_MUTEX;
152 return 0;
155 afs_int32
156 ka_SingleServerConn(char *cell, char *server, /* name of server to contact */
157 int service, struct ktc_token * token,
158 struct ubik_client ** conn)
160 afs_int32 code;
161 struct rx_connection *serverconns[2];
162 struct rx_securityClass *sc;
163 int si; /* security class index */
164 struct afsconf_cell cellinfo; /* for cell auth server list */
165 int i;
166 int match;
167 char sname[MAXHOSTCHARS];
168 int snamel;
170 LOCK_GLOBAL_MUTEX;
171 code = ka_GetServers(cell, &cellinfo);
172 if (code) {
173 UNLOCK_GLOBAL_MUTEX;
174 return code;
177 lcstring(sname, server, sizeof(sname));
178 snamel = strlen(sname);
179 match = -1;
180 for (i = 0; i < cellinfo.numServers; i++) {
181 if (strncmp(cellinfo.hostName[i], sname, snamel) == 0) {
182 if (match >= 0) {
183 UNLOCK_GLOBAL_MUTEX;
184 return KANOCELLS;
185 } else
186 match = i;
189 if (match < 0) {
190 UNLOCK_GLOBAL_MUTEX;
191 return KANOCELLS;
194 code = rx_Init(0);
195 if (code) {
196 UNLOCK_GLOBAL_MUTEX;
197 return code;
200 code = ka_GetSecurity(service, token, &sc, &si);
201 if (code) {
202 UNLOCK_GLOBAL_MUTEX;
203 return code;
205 #ifdef AFS_PTHREAD_ENV
206 serverconns[0] =
207 rx_GetCachedConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
208 cellinfo.hostAddr[match].sin_port, service, sc,
209 si);
210 #else
211 serverconns[0] =
212 rx_NewConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
213 cellinfo.hostAddr[match].sin_port, service, sc, si);
214 #endif
215 serverconns[1] = 0; /* terminate list */
217 /* next, pass list of server rx_connections (in serverconns), and a place
218 * to put the returned client structure that we'll use in all of our rpc
219 * calls (via ubik_Call) */
220 *conn = 0;
221 code = ubik_ClientInit(serverconns, conn);
222 rxs_Release(sc);
223 UNLOCK_GLOBAL_MUTEX;
224 if (code)
225 return KAUBIKINIT;
226 return 0;
229 afs_int32
230 ka_AuthSpecificServersConn(int service, struct ktc_token * token,
231 struct afsconf_cell * cellinfo,
232 struct ubik_client ** conn)
234 afs_int32 code;
235 struct rx_connection *serverconns[MAXSERVERS];
236 struct rx_securityClass *sc;
237 int si; /* security class index */
238 int i;
240 LOCK_GLOBAL_MUTEX;
241 code = rx_Init(0);
242 if (code) {
243 UNLOCK_GLOBAL_MUTEX;
244 return code;
247 code = ka_GetSecurity(service, token, &sc, &si);
248 if (code) {
249 UNLOCK_GLOBAL_MUTEX;
250 return code;
253 for (i = 0; i < cellinfo->numServers; i++)
254 #ifdef AFS_PTHREAD_ENV
255 serverconns[i] =
256 rx_GetCachedConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
257 cellinfo->hostAddr[i].sin_port, service,
258 sc, si);
259 #else
260 serverconns[i] =
261 rx_NewConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
262 cellinfo->hostAddr[i].sin_port, service, sc, si);
263 #endif
264 serverconns[cellinfo->numServers] = 0; /* terminate list */
266 /* next, pass list of server rx_connections (in serverconns), and a place
267 * to put the returned client structure that we'll use in all of our rpc
268 * calls (via ubik_Call) */
269 *conn = 0;
270 code = ubik_ClientInit(serverconns, conn);
271 rxs_Release(sc);
272 UNLOCK_GLOBAL_MUTEX;
273 if (code)
274 return KAUBIKINIT;
275 return 0;
278 afs_int32
279 ka_AuthServerConn(char *cell, int service, struct ktc_token * token,
280 struct ubik_client ** conn)
282 afs_int32 code;
283 struct rx_connection *serverconns[MAXSERVERS];
284 struct rx_securityClass *sc;
285 int si; /* security class index */
286 int i;
287 struct afsconf_cell cellinfo; /* for cell auth server list */
289 LOCK_GLOBAL_MUTEX;
290 code = ka_GetServers(cell, &cellinfo);
291 if (code) {
292 UNLOCK_GLOBAL_MUTEX;
293 return code;
296 code = rx_Init(0);
297 if (code) {
298 UNLOCK_GLOBAL_MUTEX;
299 return code;
302 code = ka_GetSecurity(service, token, &sc, &si);
303 if (code) {
304 UNLOCK_GLOBAL_MUTEX;
305 return code;
308 for (i = 0; i < cellinfo.numServers; i++)
309 #ifdef AFS_PTHREAD_ENV
310 serverconns[i] =
311 rx_GetCachedConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
312 cellinfo.hostAddr[i].sin_port, service, sc,
313 si);
314 #else
315 serverconns[i] =
316 rx_NewConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
317 cellinfo.hostAddr[i].sin_port, service, sc, si);
318 #endif
319 serverconns[cellinfo.numServers] = 0; /* terminate list */
321 /* next, pass list of server rx_connections (in serverconns), and a place
322 * to put the returned client structure that we'll use in all of our rpc
323 * calls (via ubik_Call) */
324 *conn = 0;
325 code = ubik_ClientInit(serverconns, conn);
326 rxs_Release(sc);
327 UNLOCK_GLOBAL_MUTEX;
328 if (code)
329 return KAUBIKINIT;
330 return 0;
333 static afs_int32
334 CheckTicketAnswer(ka_BBS * oanswer, afs_int32 challenge,
335 struct ktc_token *token, struct ktc_principal *caller,
336 struct ktc_principal *server, char *label,
337 afs_int32 * pwexpires)
339 struct ka_ticketAnswer *answer;
340 unsigned char tempc;
342 answer = (struct ka_ticketAnswer *)oanswer->SeqBody;
344 if (challenge != ntohl(answer->challenge))
345 return KABADPROTOCOL;
346 memcpy(&token->sessionKey, &answer->sessionKey,
347 sizeof(token->sessionKey));
348 token->startTime = ntohl(answer->startTime);
349 token->endTime = ntohl(answer->endTime);
350 token->kvno = (short)ntohl(answer->kvno);
351 token->ticketLen = ntohl(answer->ticketLen);
353 if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0)
354 return KABADPROTOCOL;
355 if ((token->ticketLen < MINKTCTICKETLEN)
356 || (token->ticketLen > MAXKTCTICKETLEN))
357 return KABADPROTOCOL;
360 char *strings = answer->name;
361 int len;
362 #undef chkstr
363 #define chkstr(field) \
364 len = strlen (strings); \
365 if (len > MAXKTCNAMELEN) return KABADPROTOCOL;\
366 if ((field) && strcmp (field, strings)) return KABADPROTOCOL;\
367 strings += len+1
369 #define chknostr() \
370 len = strlen(strings); \
371 if (len > MAXKTCNAMELEN) return KABADPROTOCOL; \
372 strings += len+1
374 if (caller) {
375 chkstr(caller->name);
376 chkstr(caller->instance);
377 chkstr(caller->cell);
378 } else {
379 chknostr();
380 chknostr();
381 chknostr();
383 if (server) {
384 chkstr(server->name);
385 chkstr(server->instance);
386 } else {
387 chknostr();
388 chknostr();
391 if (oanswer->SeqLen -
392 ((strings - oanswer->SeqBody) + token->ticketLen + KA_LABELSIZE)
393 >= (ENCRYPTIONBLOCKSIZE + 12)
395 return KABADPROTOCOL;
397 memcpy(token->ticket, strings, token->ticketLen);
398 strings += token->ticketLen;
399 if (memcmp(strings, label, KA_LABELSIZE) != 0)
400 return KABADPROTOCOL;
402 if (pwexpires) {
403 afs_int32 temp;
404 strings += KA_LABELSIZE;
405 temp = round_up_to_ebs((strings - oanswer->SeqBody));
407 if (oanswer->SeqLen > temp) {
408 strings = oanswer->SeqBody + temp;
409 memcpy(&temp, strings, sizeof(afs_int32));
410 tempc = ntohl(temp) >> 24;
411 /* don't forget this if you add any more fields!
412 * strings += sizeof(afs_int32);
414 } else {
415 tempc = 255;
417 *pwexpires = tempc;
421 return 0;
424 /* call this instead of stub and we'll guarantee to find a host that's up.
425 * this doesn't handle UNOTSYNC very well, should use ubik_Call if you care
427 static afs_int32
428 kawrap_ubik_Call(int (*aproc) (), struct ubik_client *aclient,
429 afs_int32 aflags, void *p1, void *p2, void *p3, void *p4,
430 void *p5, void *p6, void *p7, void *p8)
432 afs_int32 code, lcode;
433 int count;
434 int pass;
436 /* First pass only checks servers known running. Second checks all.
437 * Once we've cycled through all the servers and still nothing, return
438 * error code from the last server tried.
440 for (pass = 0, aflags |= UPUBIKONLY; pass < 2;
441 pass++, aflags &= ~UPUBIKONLY) {
442 code = 0;
443 count = 0;
444 do { /* Cycle through the servers */
445 lcode = code;
446 code =
447 ubik_CallIter(aproc, aclient, aflags, &count, (long) p1,
448 (long) p2, (long) p3, (long) p4,
449 (long) p5, (long) p6, (long) p7,
450 (long) p8, 0, 0, 0, 0, 0, 0, 0, 0);
451 } while ((code == UNOQUORUM) || (code == UNOTSYNC)
452 || (code == KALOCKED) || (code == -1));
454 if (code != UNOSERVERS)
455 break;
458 /* If cycled through all the servers, return the last error code */
459 if ((code == UNOSERVERS) && lcode) {
460 code = lcode;
462 return code;
465 /* This is the interface to the AuthServer RPC routine Authenticate. It
466 formats the request packet, calls the encryption routine on the answer,
467 calls Authenticate, and decrypts the response. The response is checked for
468 correctness and its contents are copied into the token. */
470 /* Errors:
471 KABADKEY = the key failed when converted to a key schedule. Probably bad
472 parity.
473 KAUBIKCALL - the call to Ubik returned an error, probably a communication
474 failure such as timeout.
475 KABADPROTOCOL - the returned packet was in error. Since a packet was
476 returned it can be presumed that the AuthServer correctly interpreted
477 the response. This may indicate an inauthentic AuthServer.
478 <other> - errors generated by the server process are returned directly.
481 afs_int32
482 ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * conn, /* Ubik connection to the AuthServer in
483 * the desired cell */
484 int service, /* ticket granting or admin service */
485 struct ktc_encryptionKey * key, Date start, Date end, /* ticket lifetime */
486 struct ktc_token * token, afs_int32 * pwexpires)
487 { /* days until it expires */
488 afs_int32 code;
489 DES_key_schedule schedule;
490 Date request_time;
491 struct ka_gettgtRequest request;
492 struct ka_gettgtAnswer answer_old;
493 struct ka_ticketAnswer answer;
494 ka_CBS arequest;
495 ka_BBS oanswer;
496 char *req_label;
497 char *ans_label;
498 int version;
500 LOCK_GLOBAL_MUTEX;
501 if ((code = DES_key_sched(ktc_to_cblock(key), &schedule))) {
502 UNLOCK_GLOBAL_MUTEX;
503 return KABADKEY;
506 if (service == KA_MAINTENANCE_SERVICE) {
507 req_label = KA_GETADM_REQ_LABEL;
508 ans_label = KA_GETADM_ANS_LABEL;
509 } else if (service == KA_TICKET_GRANTING_SERVICE) {
510 req_label = KA_GETTGT_REQ_LABEL;
511 ans_label = KA_GETTGT_ANS_LABEL;
512 } else {
513 UNLOCK_GLOBAL_MUTEX;
514 return KABADARGUMENT;
517 request_time = time(0);
518 request.time = htonl(request_time);
519 memcpy(request.label, req_label, sizeof(request.label));
520 arequest.SeqLen = sizeof(request);
521 arequest.SeqBody = (char *)&request;
522 DES_pcbc_encrypt(arequest.SeqBody, arequest.SeqBody, arequest.SeqLen,
523 &schedule, ktc_to_cblockptr(key), ENCRYPT);
525 oanswer.MaxSeqLen = sizeof(answer);
526 oanswer.SeqLen = 0;
527 oanswer.SeqBody = (char *)&answer;
529 version = 2;
530 code =
531 kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
532 (void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
533 if (code == RXGEN_OPCODE) {
534 oanswer.MaxSeqLen = sizeof(answer);
535 oanswer.SeqBody = (char *)&answer;
536 version = 1;
537 code =
538 ubik_KAA_Authenticate(conn, 0, name, instance, start, end,
539 &arequest, &oanswer);
540 if (code == RXGEN_OPCODE) {
541 oanswer.MaxSeqLen = sizeof(answer_old);
542 oanswer.SeqBody = (char *)&answer_old;
543 version = 0;
544 code =
545 ubik_KAA_Authenticate_old(conn, 0, name, instance,
546 start, end, &arequest, &oanswer);
548 if (code == RXGEN_OPCODE) {
549 code = KAOLDINTERFACE;
552 if (code) {
553 UNLOCK_GLOBAL_MUTEX;
554 if ((code >= KAMINERROR) && (code <= KAMAXERROR))
555 return code;
556 return KAUBIKCALL;
558 DES_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
559 &schedule, ktc_to_cblockptr(key), DECRYPT);
561 switch (version) {
562 case 1:
563 case 2:
565 struct ktc_principal caller;
566 strcpy(caller.name, name);
567 strcpy(caller.instance, instance);
568 strcpy(caller.cell, "");
569 code =
570 CheckTicketAnswer(&oanswer, request_time + 1, token, &caller,
571 0, ans_label, pwexpires);
572 if (code) {
573 UNLOCK_GLOBAL_MUTEX;
574 return code;
577 break;
578 case 0:
579 answer_old.time = ntohl(answer_old.time);
580 answer_old.ticket_len = ntohl(answer_old.ticket_len);
581 if ((answer_old.time != request_time + 1)
582 || (answer_old.ticket_len < MINKTCTICKETLEN)
583 || (answer_old.ticket_len > MAXKTCTICKETLEN)) {
584 UNLOCK_GLOBAL_MUTEX;
585 return KABADPROTOCOL;
588 char *label = ((char *)answer_old.ticket) + answer_old.ticket_len;
590 if (strncmp(label, ans_label, sizeof(answer_old.label))) {
591 UNLOCK_GLOBAL_MUTEX;
592 return KABADPROTOCOL;
594 token->startTime = start;
595 token->endTime = end;
596 token->kvno = ntohl(answer_old.kvno);
597 token->ticketLen = answer_old.ticket_len;
598 memcpy(token->ticket, answer_old.ticket, sizeof(token->ticket));
599 memcpy(&token->sessionKey, &answer_old.sessionkey,
600 sizeof(struct ktc_encryptionKey));
602 break;
603 default:
604 UNLOCK_GLOBAL_MUTEX;
605 return KAINTERNALERROR;
608 UNLOCK_GLOBAL_MUTEX;
609 return 0;
612 afs_int32
613 ka_GetToken(char *name, char *instance, char *cell, char *cname, char *cinst, struct ubik_client * conn, /* Ubik conn to cell's AuthServer */
614 Date start, Date end, /* desired ticket lifetime */
615 struct ktc_token * auth_token, char *auth_domain,
616 struct ktc_token * token)
618 struct ka_getTicketTimes times;
619 struct ka_getTicketAnswer answer_old;
620 struct ka_ticketAnswer answer;
621 afs_int32 code;
622 ka_CBS aticket;
623 ka_CBS atimes;
624 ka_BBS oanswer;
625 char *strings;
626 int len;
627 DES_key_schedule schedule;
628 int version;
629 afs_int32 pwexpires;
631 LOCK_GLOBAL_MUTEX;
632 aticket.SeqLen = auth_token->ticketLen;
633 aticket.SeqBody = auth_token->ticket;
635 code = DES_key_sched(ktc_to_cblock(&auth_token->sessionKey), &schedule);
636 if (code) {
637 UNLOCK_GLOBAL_MUTEX;
638 return KABADKEY;
641 times.start = htonl(start);
642 times.end = htonl(end);
643 DES_ecb_encrypt((DES_cblock *)&times, (DES_cblock *)&times, &schedule,
644 ENCRYPT);
646 atimes.SeqLen = sizeof(times);
647 atimes.SeqBody = (char *)&times;
649 oanswer.SeqLen = 0;
650 oanswer.MaxSeqLen = sizeof(answer);
651 oanswer.SeqBody = (char *)&answer;
653 version = 1;
654 code =
655 ubik_KAT_GetTicket(conn, 0, auth_token->kvno, auth_domain,
656 &aticket, name, instance, &atimes, &oanswer);
657 if (code == RXGEN_OPCODE) {
658 oanswer.SeqLen = 0; /* this may be set by first call */
659 oanswer.MaxSeqLen = sizeof(answer_old);
660 oanswer.SeqBody = (char *)&answer_old;
661 version = 0;
662 code =
663 ubik_KAT_GetTicket_old(conn, 0, auth_token->kvno,
664 auth_domain, &aticket, name, instance, &atimes,
665 &oanswer);
666 if (code == RXGEN_OPCODE) {
667 code = KAOLDINTERFACE;
670 if (code) {
671 UNLOCK_GLOBAL_MUTEX;
672 if ((code >= KAMINERROR) && (code <= KAMAXERROR))
673 return code;
674 return KAUBIKCALL;
677 DES_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
678 &schedule, ktc_to_cblockptr(&auth_token->sessionKey),
679 DECRYPT);
681 switch (version) {
682 case 1:
684 struct ktc_principal server;
685 strcpy(server.name, name);
686 strcpy(server.instance, instance);
687 code =
688 CheckTicketAnswer(&oanswer, 0, token, 0, &server,
689 KA_GETTICKET_ANS_LABEL, &pwexpires);
690 if (code) {
691 UNLOCK_GLOBAL_MUTEX;
692 return code;
695 break;
696 case 0:
697 token->startTime = ntohl(answer_old.startTime);
698 token->endTime = ntohl(answer_old.endTime);
699 token->ticketLen = ntohl(answer_old.ticketLen);
700 token->kvno = ntohl(answer_old.kvno);
701 memcpy(&token->sessionKey, &answer_old.sessionKey,
702 sizeof(token->sessionKey));
704 if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0) {
705 UNLOCK_GLOBAL_MUTEX;
706 return KABADPROTOCOL;
708 if ((token->ticketLen < MINKTCTICKETLEN)
709 || (token->ticketLen > MAXKTCTICKETLEN)) {
710 UNLOCK_GLOBAL_MUTEX;
711 return KABADPROTOCOL;
713 strings = answer_old.name;
714 len = strlen(strings); /* check client name */
715 if ((len < 1) || (len > MAXKTCNAMELEN)) {
716 UNLOCK_GLOBAL_MUTEX;
717 return KABADPROTOCOL;
719 strings += len + 1; /* check client instance */
720 len = strlen(strings);
721 if ((len < 0) || (len > MAXKTCNAMELEN)) {
722 UNLOCK_GLOBAL_MUTEX;
723 return KABADPROTOCOL;
725 strings += len + 1;
726 len = strlen(strings); /* check client cell */
727 if ((len < 0) || (len > MAXKTCNAMELEN)) {
728 UNLOCK_GLOBAL_MUTEX;
729 return KABADPROTOCOL;
731 strings += len + 1;
732 len = strlen(strings); /* check server name */
733 if ((len < 1) || (len > MAXKTCNAMELEN) || strcmp(name, strings)) {
734 UNLOCK_GLOBAL_MUTEX;
735 return KABADPROTOCOL;
737 strings += len + 1;
738 len = strlen(strings); /* check server instance */
739 if ((len < 0) || (len > MAXKTCNAMELEN) || strcmp(instance, strings)) {
740 UNLOCK_GLOBAL_MUTEX;
741 return KABADPROTOCOL;
743 strings += len + 1;
745 if ((strings - oanswer.SeqBody + token->ticketLen) - oanswer.SeqLen >=
746 ENCRYPTIONBLOCKSIZE) {
747 UNLOCK_GLOBAL_MUTEX;
748 return KABADPROTOCOL;
750 memcpy(token->ticket, strings, token->ticketLen);
752 break;
753 default:
754 UNLOCK_GLOBAL_MUTEX;
755 return KAINTERNALERROR;
758 UNLOCK_GLOBAL_MUTEX;
759 return 0;
762 afs_int32
763 ka_ChangePassword(char *name, char *instance, struct ubik_client * conn, /* Ubik connection to the AuthServer in
764 * the desired cell */
765 struct ktc_encryptionKey * oldkey,
766 struct ktc_encryptionKey * newkey)
768 afs_int32 code;
770 LOCK_GLOBAL_MUTEX;
771 code =
772 ubik_KAM_SetPassword(conn, UBIK_CALL_NEW, name, instance, 0, *(EncryptionKey *)newkey);
773 UNLOCK_GLOBAL_MUTEX;
774 return code;