static long GetTicket(long *versionP, struct ktc_encryptionKey *session, int *ticketLenP, char *ticket, char *cell) { long code; /* create random session key, using key for seed to good random */ des_init_random_number_generator(ktc_to_cblock(&serviceKey)); code = des_random_key(ktc_to_cblock(session)); if (code) return code; /* now create the actual ticket */ *ticketLenP = 0; code = tkt_MakeTicket(ticket, ticketLenP, &serviceKey, RXKST_CLIENT_NAME, RXKST_CLIENT_INST, cell, /*start,end */ 0, 0xffffffff, session, /*host */ 0, RXKST_SERVER_NAME, RXKST_SERVER_NAME); /* parms were buffer, ticketlen, key to seal ticket with, principal name, * instance and cell, start time, end time, session key to seal in ticket, * inet host, server name and server instance */ if (code) return code; *versionP = serviceKeyVersion; return 0; }
static void StringToKey(char *str, char *cell, /* cell for password */ struct ktc_encryptionKey *key) { DES_key_schedule schedule; DES_cblock temp_key; DES_cblock ivec; char password[BUFSIZ]; int passlen; strncpy(password, str, sizeof(password)); if ((passlen = strlen(password)) < sizeof(password) - 1) strncat(password, cell, sizeof(password) - passlen); if ((passlen = strlen(password)) > sizeof(password)) passlen = sizeof(password); memcpy(&ivec, "kerberos", 8); memcpy(&temp_key, "kerberos", 8); DES_set_odd_parity(&temp_key); DES_key_sched(&temp_key, &schedule); DES_cbc_cksum((DES_cblock *) password, &ivec, passlen, &schedule, &ivec); memcpy(&temp_key, &ivec, 8); DES_set_odd_parity(&temp_key); DES_key_sched(&temp_key, &schedule); DES_cbc_cksum((DES_cblock *)password, ktc_to_cblock(key), passlen, &schedule, &ivec); DES_set_odd_parity(ktc_to_cblock(key)); }
static afs_int32 GenericAuth(struct afsconf_dir *adir, struct rx_securityClass **astr, afs_int32 *aindex, rxkad_level enclevel) { char tbuffer[256]; struct ktc_encryptionKey key, session; struct rx_securityClass *tclass; afs_int32 kvno; afs_int32 ticketLen; register afs_int32 code; /* first, find the right key and kvno to use */ code = afsconf_GetLatestKey(adir, &kvno, &key); if (code) { return QuickAuth(astr, aindex); } /* next create random session key, using key for seed to good random */ des_init_random_number_generator(ktc_to_cblock(&key)); code = des_random_key(ktc_to_cblock(&session)); if (code) { return QuickAuth(astr, aindex); } /* now create the actual ticket */ ticketLen = sizeof(tbuffer); memset(tbuffer, '\0', sizeof(tbuffer)); code = tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0, 0xffffffff, &session, 0, "afs", ""); /* parms were buffer, ticketlen, key to seal ticket with, principal * name, instance and cell, start time, end time, session key to seal * in ticket, inet host, server name and server instance */ if (code) { return QuickAuth(astr, aindex); } /* Next, we have ticket, kvno and session key, authenticate the connection. * We use a magic # instead of a constant because of basic compilation * order when compiling the system from scratch (rx/rxkad.h isn't installed * yet). */ tclass = (struct rx_securityClass *) rxkad_NewClientSecurityObject(enclevel, &session, kvno, ticketLen, tbuffer); *astr = tclass; *aindex = RX_SECIDX_KAD; return 0; }
static afs_int32 check_auth(struct packet *pkt, char *auth, int authLen, struct ktc_encryptionKey *key, char *name, char *inst, char *cell) { char *packet; DES_key_schedule schedule; afs_int32 cksum; afs_int32 time_sec; int byteOrder = pkt->byteOrder; DES_key_sched(ktc_to_cblock(key), &schedule); DES_pcbc_encrypt(auth, auth, authLen, &schedule, ktc_to_cblockptr(key), DECRYPT); packet = auth; if (strcmp(packet, name) != 0) return KABADTICKET; packet += strlen(packet) + 1; if (strcmp(packet, inst) != 0) return KABADTICKET; packet += strlen(packet) + 1; if (strcmp(packet, cell) != 0) return KABADTICKET; packet += strlen(packet) + 1; getint(cksum); /* Comments in the original IBM source suggest this byte was/is "time_msec" */ packet++; getint(time_sec); if ((packet - auth) > authLen) return KABADTICKET; return 0; }
int tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key, char *name, char *inst, char *cell, afs_uint32 start, afs_uint32 end, struct ktc_encryptionKey *sessionKey, afs_uint32 host, char *sname, char *sinst) { int code; union Key_schedule_safe schedule; *ticketLen = 0; /* in case we return early */ code = assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host, sessionKey, start, end, sname, sinst); *ticketLen = round_up_to_ebs(*ticketLen); /* round up */ if (code) return -1; /* encrypt ticket */ if ((code = key_sched(ktc_to_cblock(key), schedule.schedule))) { printf("In tkt_MakeTicket: key_sched returned %d\n", code); return RXKADBADKEY; } pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, ktc_to_cblockptr(key), ENCRYPT); return 0; }
static afs_int32 create_cipher(char *cipher, int *cipherLen, struct ktc_encryptionKey *sessionKey, char *sname, char *sinst, Date start, Date end, afs_int32 kvno, char *ticket, int ticketLen, struct ktc_encryptionKey *key) { char *answer; int slen; unsigned char life = time_to_life(start, end); int len; DES_key_schedule schedule; afs_int32 code; answer = cipher; len = sizeof(*sessionKey) + strlen(sname) + strlen(sinst) + strlen(lrealm) + 3 /*nulls */ + 3 + ticketLen + sizeof(Date); if (len > *cipherLen) return KAANSWERTOOLONG; if (ticketLen > 255) return KAANSWERTOOLONG; if (kvno > 255) return KAANSWERTOOLONG; memcpy(answer, sessionKey, sizeof(*sessionKey)); answer += sizeof(*sessionKey); putstr(sname); putstr(sinst); putstr(lrealm); *answer++ = life; *answer++ = (unsigned char)kvno; *answer++ = (unsigned char)ticketLen; memcpy(answer, ticket, ticketLen); answer += ticketLen; putint(start); if (krb_udp_debug) { printf("Printing ticket (%d) and date: ", ticketLen); ka_PrintBytes(ticket, ticketLen); ka_PrintBytes(answer - 4, 4); printf("\n"); } if ((code = DES_key_sched(ktc_to_cblock(key), &schedule))) printf("In KAAuthenticate: key_sched returned %d\n", code); DES_pcbc_encrypt(cipher, cipher, len, &schedule, ktc_to_cblockptr(key), ENCRYPT); *cipherLen = round_up_to_ebs(len); if (krb_udp_debug) { printf("Printing cipher (%d): ", *cipherLen); ka_PrintBytes(cipher, *cipherLen); printf("\n"); } return 0; }
int tkt_DecodeTicket(char *asecret, afs_int32 ticketLen, struct ktc_encryptionKey *key, char *name, char *inst, char *cell, struct ktc_encryptionKey *sessionKey, afs_int32 * host, afs_uint32 * start, afs_uint32 * end) { char clear_ticket[MAXKTCTICKETLEN]; char *ticket; union Key_schedule_safe schedule; int code; if (ticketLen == 0) return RXKADBADTICKET; /* no ticket */ if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */ (ticketLen > MAXKTCTICKETLEN) || /* maximum legal ticket size */ ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */ return RXKADBADTICKET; if (key_sched(ktc_to_cblock(key), schedule.schedule)) return RXKADBADKEY; ticket = clear_ticket; pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, ktc_to_cblockptr(key), DECRYPT); code = decode_athena_ticket(ticket, ticketLen, name, inst, cell, host, (struct ktc_encryptionKey *)sessionKey, start, end); if (code) return RXKADBADTICKET; code = tkt_CheckTimes(*start, *end, time(0)); if (code == 0) return RXKADNOAUTH; else if (code == -1) return RXKADEXPIRED; else if (code < -1) return RXKADBADTICKET; return 0; }
static void Andrew_StringToKey(char *str, char *cell, /* cell for password */ struct ktc_encryptionKey *key) { char password[8 + 1]; /* crypt's limit is 8 chars anyway */ int i; int passlen; memset(key, 0, sizeof(struct ktc_encryptionKey)); strncpy(password, cell, 8); passlen = strlen(str); if (passlen > 8) passlen = 8; for (i = 0; i < passlen; i++) password[i] ^= str[i]; for (i = 0; i < 8; i++) if (password[i] == '\0') password[i] = 'X'; /* crypt only considers the first 8 characters of password but for some * reason returns eleven characters of result (plus the two salt chars). */ strncpy((char *)key, (char *)crypt(password, "p1") + 2, sizeof(struct ktc_encryptionKey)); /* parity is inserted into the LSB so leftshift each byte up one bit. This * allows ascii characters with a zero MSB to retain as much significance * as possible. */ { char *keybytes = (char *)key; unsigned int temp; for (i = 0; i < 8; i++) { temp = (unsigned int)keybytes[i]; keybytes[i] = (unsigned char)(temp << 1); } } DES_set_odd_parity(ktc_to_cblock(key)); }
afs_int32 UDP_GetTicket(int ksoc, struct packet *pkt, afs_int32 kvno, char *authDomain, char *ticket, int ticketLen, char *auth, int authLen) { afs_int32 code; struct ktc_encryptionKey tgskey; char name[MAXKTCNAMELEN]; char inst[MAXKTCNAMELEN]; char cell[MAXKTCREALMLEN]; struct ktc_encryptionKey authSessionKey; afs_int32 host; Date start; Date authEnd; Date now = time(0); int celllen; int import; char *packet; int slen; int byteOrder = pkt->byteOrder; char sname[MAXKTCNAMELEN]; char sinst[MAXKTCNAMELEN]; afs_int32 time_ws; unsigned char life; struct ubik_trans *tt; afs_int32 to; struct kaentry caller; struct kaentry server; Date reqEnd; struct ktc_encryptionKey sessionKey; int newTicketLen; char newTicket[MAXKTCTICKETLEN]; char cipher[2 * MAXKTCTICKETLEN]; /* put encrypted part of answer here */ int cipherLen; struct packet ans; COUNT_REQ(UGetTicket); if ((code = InitAuthServ(&tt, LOCKREAD, this_op))) goto fail; code = ka_LookupKvno(tt, KA_TGS_NAME, ((strlen(authDomain) > 0) ? authDomain : lrealm), kvno, &tgskey); if (code) goto abort; code = tkt_DecodeTicket(ticket, ticketLen, &tgskey, name, inst, cell, &authSessionKey, &host, &start, &authEnd); pkt->name = name; pkt->inst = inst; pkt->realm = cell; if (code) { code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */ goto abort; } save_principal(udptgsPrincipal, name, inst, cell); code = tkt_CheckTimes(start, authEnd, now); if (code <= 0) { if (code == -1) { code = KERB_ERR_SERVICE_EXP; /* was RXKADEXPIRED */ goto abort; } code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */ goto abort; } celllen = strlen(cell); import = 0; if ((strlen(authDomain) > 0) && (strcmp(authDomain, lrealm) != 0)) import = 1; if (import && (celllen == 0)) { code = KERB_ERR_PKT_VER; /* was KABADTICKET */ goto abort; } if (celllen == 0) { strncpy(cell, lrealm, MAXKTCREALMLEN - 1); cell[MAXKTCREALMLEN - 1] = 0; }; if (!krb4_cross && strcmp(lrealm, cell) != 0) { code = KERB_ERR_PRINCIPAL_UNKNOWN; goto abort; } if (krb_udp_debug) { printf("UGetTicket: got ticket from '%s'.'%s'@'%s'\n", name, inst, cell); } code = check_auth(pkt, auth, authLen, &authSessionKey, name, inst, cell); if (code) goto abort; /* authenticator and all is OK so read actual request */ packet = pkt->rest; getint(time_ws); life = *(unsigned char *)packet++; getstr(sname); getstr(sinst); start = now; reqEnd = life_to_time(start, life); if (krb_udp_debug) { printf("UGetTicket: request for server '%s'.'%s'\n", sname, sinst); } save_principal(udptgsServerPrincipal, sname, sinst, 0); if (import) { strcpy(caller.userID.name, name); strcpy(caller.userID.instance, inst); caller.max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME); } else { code = FindBlock(tt, name, inst, &to, &caller); if (code) goto abort; if (to == 0) { ka_PrintUserID("GetTicket: User ", name, inst, " unknown.\n"); code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */ goto abort; } if (ntohl(caller.flags) & KAFNOTGS) { code = KERB_ERR_AUTH_EXP; /* was KABADUSER */ goto abort; } } code = FindBlock(tt, sname, sinst, &to, &server); /* get server's entry */ if (code) goto abort; if (to == 0) { /* entry not found */ ka_PrintUserID("GetTicket: Server ", sname, sinst, " unknown.\n"); code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */ goto abort; } code = ubik_EndTrans(tt); if (code) goto fail; if (ntohl(server.flags) & KAFNOSEAL) return KABADSERVER; code = DES_new_random_key(ktc_to_cblock(&sessionKey)); if (code) { code = KERB_ERR_NULL_KEY; /* was KANOKEYS */ goto fail; } reqEnd = umin(umin(reqEnd, authEnd), umin(start + ntohl(caller.max_ticket_lifetime), start + ntohl(server.max_ticket_lifetime))); code = tkt_MakeTicket(newTicket, &newTicketLen, &server.key, caller.userID.name, caller.userID.instance, cell, start, reqEnd, &sessionKey, htonl(pkt->from.sin_addr.s_addr), server.userID.name, server.userID.instance); if (code) goto fail; cipherLen = sizeof(cipher); code = create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst, start, reqEnd, ntohl(server.key_version), newTicket, newTicketLen, &authSessionKey); if (code) goto fail; code = create_reply(&ans, name, inst, start, reqEnd, 0, cipher, cipherLen); if (code) goto fail; code = sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from, sizeof(pkt->from)); if (code != ans.len) { perror("calling sendto"); code = -1; goto fail; } if (cipherLen != 0) { KALOG(name, inst, sname, sinst, NULL, host, LOG_GETTICKET); } osi_audit(UDPGetTicketEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_STR, cell, AUD_STR, sname, AUD_STR, sinst, AUD_END); return 0; abort: ubik_AbortTrans(tt); fail: osi_audit(UDPGetTicketEvent, code, AUD_STR, name, AUD_STR, inst, AUD_STR, NULL, AUD_STR, NULL, AUD_STR, NULL, AUD_END); return code; }
afs_int32 UDP_Authenticate(int ksoc, struct sockaddr_in *client, char *name, char *inst, Date startTime, Date endTime, char *sname, char *sinst) { struct ubik_trans *tt; afs_int32 to; /* offset of block */ struct kaentry tentry; afs_int32 tgskvno; /* key version of service key */ struct ktc_encryptionKey tgskey; /* service key for encrypting ticket */ int tgt; Date now = time(0); afs_int32 code; char ticket[MAXKTCTICKETLEN]; /* our copy of the ticket */ int ticketLen; struct ktc_encryptionKey sessionKey; /* we have to invent a session key */ char cipher[2 * MAXKTCTICKETLEN]; /* put encrypted part of answer here */ int cipherLen; struct packet ans; COUNT_REQ(UAuthenticate); if (!name_instance_legal(name, inst)) return KERB_ERR_NAME_EXP; /* KABADNAME */ if ((code = InitAuthServ(&tt, LOCKREAD, this_op))) return code; code = FindBlock(tt, name, inst, &to, &tentry); if (code) goto abort; if (to) { /* if user exists check other stuff */ afs_int32 sto; struct kaentry sentry; save_principal(udpAuthPrincipal, name, inst, 0); tgt = ((strcmp(sname, KA_TGS_NAME) == 0) && (strcmp(sinst, lrealm) == 0)); if ((ntohl(tentry.user_expiration) < now) || (tgt && (ntohl(tentry.flags) & KAFNOTGS))) { code = KERB_ERR_NAME_EXP; /* KABADUSER */ goto abort; } code = FindBlock(tt, KA_TGS_NAME, lrealm, &sto, &sentry); if (code) goto abort; if (sto == 0) { code = KANOENT; goto abort; } if ((ntohl(sentry.user_expiration) < now)) { code = KERB_ERR_NAME_EXP; /* XXX Could use another error code XXX */ goto abort; } if (abs(startTime - now) > KTC_TIME_UNCERTAINTY) { code = KERB_ERR_SERVICE_EXP; /* was KABADREQUEST */ goto abort; } if (tentry.misc_auth_bytes) { unsigned char misc_auth_bytes[4]; afs_uint32 temp; /* unsigned for safety */ afs_uint32 pwexpires; memcpy(&temp, tentry.misc_auth_bytes, sizeof(afs_uint32)); temp = ntohl(temp); unpack_long(temp, misc_auth_bytes); pwexpires = misc_auth_bytes[0]; if (pwexpires) { pwexpires = ntohl(tentry.change_password_time) + 24 * 60 * 60 * pwexpires; if (pwexpires < now) { code = KERB_ERR_AUTH_EXP; /* was KAPWEXPIRED */ goto abort; } } } /* make the ticket */ code = DES_new_random_key(ktc_to_cblock(&sessionKey)); if (code) { code = KERB_ERR_NULL_KEY; /* was KANOKEYS */ goto abort; } endTime = umin(endTime, startTime + ntohl(tentry.max_ticket_lifetime)); if ((code = ka_LookupKey(tt, sname, sinst, &tgskvno, &tgskey)) || (code = tkt_MakeTicket(ticket, &ticketLen, &tgskey, name, inst, lrealm, startTime, endTime, &sessionKey, htonl(client->sin_addr.s_addr), sname, sinst))) goto abort; cipherLen = sizeof(cipher); code = create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst, startTime, endTime, tgskvno, ticket, ticketLen, &tentry.key); if (code) goto abort; } else { /* no such user */ cipherLen = 0; tentry.key_version = 0; } code = ubik_EndTrans(tt); if (code) goto fail; code = create_reply(&ans, name, inst, startTime, endTime, ntohl(tentry.key_version), cipher, cipherLen); if (code) goto fail; if (krb_udp_debug) { printf("Sending %d bytes ending in: ", ans.len); ka_PrintBytes(ans.data + ans.len - 8, 8); printf("\n"); } code = sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)client, sizeof(*client)); if (code != ans.len) { perror("calling sendto"); code = -1; goto fail; } KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr, LOG_AUTHENTICATE); if (cipherLen != 0) { KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr, LOG_TGTREQUEST); } osi_audit(UDPAuthenticateEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_END); return 0; abort: COUNT_ABO; ubik_AbortTrans(tt); fail: osi_audit(UDPAuthenticateEvent, code, AUD_STR, name, AUD_STR, inst, AUD_END); return code; }
static int WorkerBee(struct cmd_syndesc *as, void *arock) { afs_int32 code; char *dbFile; char *outFile; afs_int32 index; struct stat info; struct kaheader header; int nentries, i, j, count; int *entrys; struct kaentry entry; dbFile = as->parms[0].items->data; /* -database */ listuheader = (as->parms[1].items ? 1 : 0); /* -uheader */ listkheader = (as->parms[2].items ? 1 : 0); /* -kheader */ listentries = (as->parms[3].items ? 1 : 0); /* -entries */ verbose = (as->parms[4].items ? 1 : 0); /* -verbose */ outFile = (as->parms[5].items ? as->parms[5].items->data : NULL); /* -rebuild */ if (outFile) { out = fopen(outFile, "w"); if (!out) { afs_com_err(whoami, errno, "opening output file %s", outFile); exit(7); } } else out = 0; fd = open(dbFile, O_RDONLY, 0); if (fd < 0) { afs_com_err(whoami, errno, "opening database file %s", dbFile); exit(6); } code = fstat(fd, &info); if (code) { afs_com_err(whoami, errno, "stat'ing file %s", dbFile); exit(6); } if ((info.st_size - UBIK_HEADERSIZE) % UBIK_BUFFERSIZE) fprintf(stderr, "DATABASE SIZE INCONSISTENT: was %d, should be (n*%d + %d), for integral n\n", (int) info.st_size, UBIK_BUFFERSIZE, UBIK_HEADERSIZE); readUbikHeader(); readDB(0, &header, sizeof(header)); code = CheckHeader(&header); if (listkheader) PrintHeader(&header); nentries = (info.st_size - (UBIK_HEADERSIZE + header.headerSize)) / sizeof(struct kaentry); entrys = calloc(nentries, sizeof(int)); for (i = 0, index = sizeof(header); i < nentries; i++, index += sizeof(struct kaentry)) { readDB(index, &entry, sizeof(entry)); if (index >= header.eofPtr) { entrys[i] |= 0x8; } else if (listentries) { PrintEntry(index, &entry); } if (entry.flags & KAFNORMAL) { entrys[i] |= 0x1; /* user entry */ if (strlen(entry.userID.name) == 0) { if (verbose) printf("Entry %d has zero length name\n", i); continue; } if (!DES_check_key_parity(ktc_to_cblock(&entry.key)) || DES_is_weak_key(ktc_to_cblock(&entry.key))) { fprintf(stderr, "Entry %d, %s, has bad key\n", i, EntryName(&entry)); continue; } if (out) { RebuildEntry(&entry); } } else if (entry.flags & KAFFREE) { entrys[i] |= 0x2; /* free entry */ } else if (entry.flags & KAFOLDKEYS) { entrys[i] |= 0x4; /* old keys block */ /* Should check the structure of the oldkeys block? */ } else { if (index < header.eofPtr) { fprintf(stderr, "Entry %d is unrecognizable\n", i); } } } /* Follow the hash chains */ for (j = 0; j < HASHSIZE; j++) { for (index = header.nameHash[j]; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* check to see if the name is hashed correctly */ i = NameHash(&entry); if (i != j) { fprintf(stderr, "Entry %" AFS_SIZET_FMT ", %s, found in hash chain %d (should be %d)\n", ((index - sizeof(struct kaheader)) / sizeof(struct kaentry)), EntryName(&entry), j, i); } /* Is it on another hash chain or circular hash chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x10) { fprintf(stderr, "Entry %d, %s, hash index %d, was found on another hash chain\n", i, EntryName(&entry), j); if (entry.next) fprintf(stderr, "Skipping rest of hash chain %d\n", j); else fprintf(stderr, "No next entry in hash chain %d\n", j); code++; break; } entrys[i] |= 0x10; /* On hash chain */ } } /* Follow the free pointers */ count = 0; for (index = header.freePtr; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* Is it on another chain or circular free chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x20) { fprintf(stderr, "Entry %d, %s, already found on free chain\n", i, EntryName(&entry)); fprintf(stderr, "Skipping rest of free chain\n"); code++; break; } entrys[i] |= 0x20; /* On free chain */ count++; } if (verbose) printf("Found %d free entries\n", count); /* Follow the oldkey blocks */ count = 0; for (index = header.kvnoPtr; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* Is it on another chain or circular free chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x40) { fprintf(stderr, "Entry %d, %s, already found on olkeys chain\n", i, EntryName(&entry)); fprintf(stderr, "Skipping rest of oldkeys chain\n"); code++; break; } entrys[i] |= 0x40; /* On free chain */ count++; } if (verbose) printf("Found %d oldkey blocks\n", count); /* Now recheck all the blocks and see if they are allocated correctly * 0x1 --> User Entry 0x10 --> On hash chain * 0x2 --> Free Entry 0x20 --> On Free chain * 0x4 --> OldKeys Entry 0x40 --> On Oldkeys chain * 0x8 --> Past EOF */ for (i = 0; i < nentries; i++) { j = entrys[i]; if (j & 0x1) { /* user entry */ if (!(j & 0x10)) badEntry(j, i); /* on hash chain? */ else if (j & 0xee) badEntry(j, i); /* anything else? */ } else if (j & 0x2) { /* free entry */ if (!(j & 0x20)) badEntry(j, i); /* on free chain? */ else if (j & 0xdd) badEntry(j, i); /* anything else? */ } else if (j & 0x4) { /* oldkeys entry */ if (!(j & 0x40)) badEntry(j, i); /* on oldkeys chain? */ else if (j & 0xbb) badEntry(j, i); /* anything else? */ } else if (j & 0x8) { /* past eof */ if (j & 0xf7) badEntry(j, i); /* anything else? */ } else badEntry(j, i); /* anything else? */ } exit(code != 0); }