Esempio n. 1
0
int
main(int argc, char *argv[])
{
    struct ktc_principal client;
    struct ktc_encryptionKey sessionkey;
    Date start, end;
    afs_int32 host;
    char key[8];
    char ticket[MAXKTCTICKETLEN];
    afs_int32 ticketLen;
    afs_int32 code;
    char bob[KA_TIMESTR_LEN];

    whoami = argv[0];
    initialize_RXK_error_table();
    initialize_KA_error_table();

    if (argc != 3) {
	printf("Usage is %s key ticket\n", whoami);
	exit(1);
    }
    if (ka_ReadBytes(argv[1], key, sizeof(key)) != 8)
	printf("Key must be 8 bytes long\n");
    if (!des_check_key_parity(key) || des_is_weak_key(key)) {
	afs_com_err(whoami, KABADKEY, "server's key for decoding ticket is bad");
	exit(1);
    }
    ticketLen = ka_ReadBytes(argv[2], ticket, sizeof(ticket));
    printf("Ticket length is %d\n", ticketLen);

    code =
	tkt_DecodeTicket(ticket, ticketLen, key, client.name, client.instance,
			 client.cell, &sessionkey, &host, &start, &end);
    if (code) {
	afs_com_err(whoami, code, "decoding ticket");
	if (code = tkt_CheckTimes(start, end, time(0)) <= 0)
	    afs_com_err(whoami, 0, "because of start or end times");
	exit(1);
    }

    if (!des_check_key_parity(&sessionkey) || des_is_weak_key(&sessionkey)) {
	afs_com_err(whoami, KABADKEY, "checking ticket's session key");
	exit(1);
    }

    ka_PrintUserID("Client is ", client.name, client.instance, 0);
    if (strlen(client.cell))
	printf("@%s", client.cell);
    printf("\nSession key is ");
    ka_PrintBytes(&sessionkey, 8);
    ka_timestr(start, bob, KA_TIMESTR_LEN);
    printf("\nGood from %s", bob);
    ka_timestr(end, bob, KA_TIMESTR_LEN);
    printf(" till %s\n", bob);
}
Esempio n. 2
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;
}
Esempio n. 3
0
/* XXX this does some copying of data in and out of the packet, but I'll bet it
 * could just do it in place, especially if I used rx_Pullup...
 */
int
rxkad_CheckResponse(struct rx_securityClass *aobj,
		    struct rx_connection *aconn, struct rx_packet *apacket)
{
    struct rxkad_sconn *sconn;
    struct rxkad_sprivate *tsp;
    struct ktc_encryptionKey serverKey;
    struct rxkad_oldChallengeResponse oldr;	/* response format */
    struct rxkad_v2ChallengeResponse v2r;
    afs_int32 tlen;		/* ticket len */
    afs_int32 kvno;		/* key version of ticket */
    char tix[MAXKTCTICKETLEN];
    afs_int32 incChallengeID;
    rxkad_level level;
    int code;
    /* ticket contents */
    struct ktc_principal client;
    struct ktc_encryptionKey sessionkey;
    afs_int32 host;
    afs_uint32 start;
    afs_uint32 end;
    unsigned int pos;
    struct rxkad_serverinfo *rock;

    sconn = (struct rxkad_sconn *)aconn->securityData;
    tsp = (struct rxkad_sprivate *)aobj->privateData;

    if (sconn->cksumSeen) {
	/* expect v2 response, leave fields in v2r in network order for cksum
	 * computation which follows decryption. */
	if (rx_GetDataSize(apacket) < sizeof(v2r))
	    return RXKADPACKETSHORT;
	rx_packetread(apacket, 0, sizeof(v2r), &v2r);
	pos = sizeof(v2r);
	/* version == 2 */
	/* ignore spare */
	kvno = ntohl(v2r.kvno);
	tlen = ntohl(v2r.ticketLen);
	if (rx_GetDataSize(apacket) < sizeof(v2r) + tlen)
	    return RXKADPACKETSHORT;
    } else {
	/* expect old format response */
	if (rx_GetDataSize(apacket) < sizeof(oldr))
	    return RXKADPACKETSHORT;
	rx_packetread(apacket, 0, sizeof(oldr), &oldr);
	pos = sizeof(oldr);

	kvno = ntohl(oldr.kvno);
	tlen = ntohl(oldr.ticketLen);
	if (rx_GetDataSize(apacket) != sizeof(oldr) + tlen)
	    return RXKADPACKETSHORT;
    }
    if ((tlen < MINKTCTICKETLEN) || (tlen > MAXKTCTICKETLEN))
	return RXKADTICKETLEN;

    rx_packetread(apacket, pos, tlen, tix);	/* get ticket */

    /*
     * We allow the ticket to be optionally decoded by an alternate
     * ticket decoder, if the function variable
     * rxkad_AlternateTicketDecoder is set. That function should
     * return a code of -1 if it wants the ticket to be decoded by
     * the standard decoder.
     */
    if (rxkad_AlternateTicketDecoder) {
	code =
	    rxkad_AlternateTicketDecoder(kvno, tix, tlen, client.name,
					 client.instance, client.cell,
					 &sessionkey, &host, &start, &end);
	if (code && code != -1) {
	    return code;
	}
    } else {
	code = -1;		/* No alternate ticket decoder present */
    }

    /*
     * If the alternate decoder is not present, or returns -1, then
     * assume the ticket is of the default style.
     */
    if (code == -1 && ((kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
	|| (kvno == RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY))) {
	code =
	    tkt_DecodeTicket5(tix, tlen, tsp->get_key, tsp->get_key_rock,
			      kvno, client.name, client.instance, client.cell,
			      &sessionkey, &host, &start, &end, 
			      tsp->flags & RXS_CONFIG_FLAGS_DISABLE_DOTCHECK);
	if (code)
	    return code;
    }

    /*
     * If the alternate decoder/kerberos 5 decoder is not present, or
     * returns -1, then assume the ticket is of the default style.
     */
    if (code == -1) {
	/* get ticket's key */
	code = (*tsp->get_key) (tsp->get_key_rock, kvno, &serverKey);
	if (code)
	    return RXKADUNKNOWNKEY;	/* invalid kvno */
	code =
	    tkt_DecodeTicket(tix, tlen, &serverKey, client.name,
			     client.instance, client.cell, &sessionkey, &host,
			     &start, &end);
	if (code)
	    return code;
    }
    code = tkt_CheckTimes(start, end, time(0));
    if (code == 0) 
	return RXKADNOAUTH;
    else if (code == -1)
	return RXKADEXPIRED;
    else if (code < -1)
	return RXKADBADTICKET;

    code = fc_keysched(&sessionkey, sconn->keysched);
    if (code)
	return RXKADBADKEY;
    memcpy(sconn->ivec, &sessionkey, sizeof(sconn->ivec));

    if (sconn->cksumSeen) {
	/* using v2 response */
	afs_uint32 cksum;	/* observed cksum */
	struct rxkad_endpoint endpoint;	/* connections endpoint */
	int i;
	afs_uint32 xor[2];

	memcpy(xor, sconn->ivec, 2 * sizeof(afs_int32));
	fc_cbc_encrypt(&v2r.encrypted, &v2r.encrypted, sizeof(v2r.encrypted),
		       sconn->keysched, xor, DECRYPT);
	cksum = rxkad_CksumChallengeResponse(&v2r);
	if (cksum != v2r.encrypted.endpoint.cksum)
	    return RXKADSEALEDINCON;
	(void)rxkad_SetupEndpoint(aconn, &endpoint);
	v2r.encrypted.endpoint.cksum = 0;
	if (memcmp(&endpoint, &v2r.encrypted.endpoint, sizeof(endpoint)) != 0)
	    return RXKADSEALEDINCON;
	for (i = 0; i < RX_MAXCALLS; i++) {
	    v2r.encrypted.callNumbers[i] =
		ntohl(v2r.encrypted.callNumbers[i]);
	    if (v2r.encrypted.callNumbers[i] < 0)
		return RXKADSEALEDINCON;
	}

	(void)rxi_SetCallNumberVector(aconn, v2r.encrypted.callNumbers);
	incChallengeID = ntohl(v2r.encrypted.incChallengeID);
	level = ntohl(v2r.encrypted.level);
    } else {
	/* expect old format response */
	fc_ecb_encrypt(&oldr.encrypted, &oldr.encrypted, sconn->keysched,
		       DECRYPT);
	incChallengeID = ntohl(oldr.encrypted.incChallengeID);
	level = ntohl(oldr.encrypted.level);
    }
    if (incChallengeID != sconn->challengeID + 1)
	return RXKADOUTOFSEQUENCE;	/* replay attempt */
    if ((level < sconn->level) || (level > rxkad_crypt))
	return RXKADLEVELFAIL;
    sconn->level = level;
    rxkad_SetLevel(aconn, sconn->level);
    INC_RXKAD_STATS(responses[rxkad_LevelIndex(sconn->level)]);
    /* now compute endpoint-specific info used for computing 16 bit checksum */
    rxkad_DeriveXORInfo(aconn, sconn->keysched, sconn->ivec, sconn->preSeq);

    /* otherwise things are ok */
    sconn->expirationTime = end;
    sconn->authenticated = 1;

    if (tsp->user_ok) {
	code = tsp->user_ok(client.name, client.instance, client.cell, kvno);
	if (code)
	    return RXKADNOAUTH;
    } else {			/* save the info for later retreival */
	int size = sizeof(struct rxkad_serverinfo);
	rock = (struct rxkad_serverinfo *)osi_Alloc(size);
	memset(rock, 0, size);
	rock->kvno = kvno;
	memcpy(&rock->client, &client, sizeof(rock->client));
	sconn->rock = rock;
    }
    return 0;
}
Esempio n. 4
0
int
process_udp_auth(int ksoc, struct packet *pkt)
{
    char *packet = pkt->rest;
    char name[MAXKTCNAMELEN];
    char inst[MAXKTCNAMELEN];
    char realm[MAXKTCREALMLEN];
    char sname[MAXKTCNAMELEN];
    char sinst[MAXKTCNAMELEN];
    int slen;
    Date now = time(0);
    Date startTime, endTime;
    unsigned char lifetime;
    afs_int32 code;

    pkt->name = packet;
    getstr(name);
    pkt->inst = packet;
    getstr(inst);
    pkt->realm = packet;
    getstr(realm);
    if (krb_udp_debug) {
	printf("Processing KDC Request from '%s'.'%s'@'%s'\n", name, inst,
	       realm);
    }

    if ((strlen(realm) > 0) && (strcmp(realm, lrealm) != 0)) {
	err_packet(ksoc, pkt, KERB_ERR_NONNULL_REALM,
		   "null realm name not allowed");
	return -1;
    }
    memcpy(&startTime, packet, sizeof(startTime));
    packet += sizeof(startTime);
    startTime = ktohl(pkt->byteOrder, startTime);
    pkt->time = startTime;
    lifetime = *packet++;
    endTime = life_to_time(startTime, lifetime);
    code = tkt_CheckTimes(startTime, endTime, now);
    if (code < 0) {
	err_packet(ksoc, pkt, KERB_ERR_BAD_LIFETIME,
		   "requested ticket lifetime invalid");
	return -1;
    }
    getstr(sname);
    getstr(sinst);
    if ((packet - pkt->data) != pkt->len) {
	err_packet(ksoc, pkt, KERB_ERR_PKT_LENGTH,
		   "packet length inconsistent");
	return -1;
    }
    pkt->rest = packet;
    code =
	UDP_Authenticate(ksoc, &pkt->from, name, inst, startTime, endTime,
			 sname, sinst);
    if (code) {
	if (code == KANOENT) {
	    code = KERB_ERR_PRINCIPAL_UNKNOWN;
	    err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
	} else if (code == KAPWEXPIRED) {
	    code = KERB_ERR_NAME_EXP;
	    err_packet(ksoc, pkt, code, "password has expired");
	} else
	    err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
    }
    return 0;
}
Esempio n. 5
0
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;
}