Esempio n. 1
0
/*!
 * Return the internal statistics collected by rx
 *
 * @return
 * 	A statistics structure which must be freed using rx_FreeStatistics
 * @notes
 * 	Takes, and releases rx_stats_mutex
 */
struct rx_statistics *
rx_GetStatistics(void) {
    struct rx_statistics *stats = rxi_Alloc(sizeof(struct rx_statistics));
    MUTEX_ENTER(&rx_stats_mutex);
    memcpy(stats, &rx_stats, sizeof(struct rx_statistics));
    MUTEX_EXIT(&rx_stats_mutex);

    return stats;
}
Esempio n. 2
0
struct rx_securityClass *
rxkad_NewClientSecurityObject(rxkad_level level,
			      struct ktc_encryptionKey *sessionkey,
			      afs_int32 kvno, int ticketLen, char *ticket)
{
    struct rx_securityClass *tsc;
    struct rxkad_cprivate *tcp;
    int code;
    int size, psize;

    rxkad_Init();

    size = sizeof(struct rx_securityClass);
    tsc = rxi_Alloc(size);
    memset((void *)tsc, 0, size);
    tsc->refCount = 1;		/* caller gets one for free */
    tsc->ops = &rxkad_client_ops;

    psize = PDATA_SIZE(ticketLen);
    tcp = rxi_Alloc(psize);
    memset((void *)tcp, 0, psize);
    tsc->privateData = (char *)tcp;
    tcp->type |= rxkad_client;
    tcp->level = level;
    code = fc_keysched(sessionkey, tcp->keysched);
    if (code) {
	rxi_Free(tcp, psize);
	rxi_Free(tsc, sizeof(struct rx_securityClass));
	return 0;		/* bad key */
    }
    memcpy((void *)tcp->ivec, (void *)sessionkey, sizeof(tcp->ivec));
    tcp->kvno = kvno;		/* key version number */
    tcp->ticketLen = ticketLen;	/* length of ticket */
    if (tcp->ticketLen > MAXKTCTICKETLEN) {
	rxi_Free(tcp, psize);
	rxi_Free(tsc, sizeof(struct rx_securityClass));
	return 0;		/* bad key */
    }
    memcpy(tcp->ticket, ticket, ticketLen);

    INC_RXKAD_STATS(clientObjects);
    return tsc;
}
Esempio n. 3
0
struct rx_identity *
rx_identity_new(rx_identity_kind kind, char *displayName, void *enameData,
		size_t enameLength)
{
    struct rx_identity *identity;

    identity = rxi_Alloc(sizeof(struct rx_identity));
    rx_identity_populate(identity, kind, displayName, enameData, enameLength);

    return identity;
}
Esempio n. 4
0
void
handle_socket_error(osi_socket so)
{
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct sock_extended_err *err;
    struct sockaddr_in addr;
    struct sockaddr *offender;
    char *controlmsgbuf;
    int code;
    struct socket *sop = (struct socket *)so;

    if (!(controlmsgbuf=rxi_Alloc(256)))
	return;
    msg.msg_name = &addr;
    msg.msg_namelen = sizeof(addr);
    msg.msg_control = controlmsgbuf;
    msg.msg_controllen = 256;
    msg.msg_flags = 0;

    code = kernel_recvmsg(sop, &msg, NULL, 0, 0,
			  MSG_ERRQUEUE|MSG_DONTWAIT|MSG_TRUNC);

    if (code < 0 || !(msg.msg_flags & MSG_ERRQUEUE))
	goto out;

    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
	if (CMSG_OK(&msg, cmsg) && cmsg->cmsg_level == SOL_IP &&
	    cmsg->cmsg_type == IP_RECVERR)
	    break;
    }
    if (!cmsg)
	goto out;
    err = CMSG_DATA(cmsg);
    offender = SO_EE_OFFENDER(err);
    
    if (offender->sa_family != AF_INET)
       goto out;

    memcpy(&addr, offender, sizeof(addr));

    if (err->ee_origin == SO_EE_ORIGIN_ICMP &&
	err->ee_type == ICMP_DEST_UNREACH &&
	err->ee_code == ICMP_FRAG_NEEDED) {
	rxi_SetPeerMtu(NULL, ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port),
		       err->ee_info);
    }
    /* other DEST_UNREACH's and TIME_EXCEEDED should be dealt with too */

out:
    rxi_Free(controlmsgbuf, 256);
    return;
}
Esempio n. 5
0
void
rx_identity_populate(struct rx_identity *identity, rx_identity_kind kind,
		     char *displayName, void *enameData, size_t enameLength)
{
    memset(identity, 0, sizeof(struct rx_identity));

    identity->kind = kind;
    identity->displayName = rxi_Alloc(strlen(displayName)+1);
    memcpy(identity->displayName, displayName, strlen(displayName)+1);

    rx_opaque_populate(&identity->exportedName, enameData, enameLength);
}
Esempio n. 6
0
struct rx_securityClass *
rxkad_NewServerSecurityObject(rxkad_level level, void *get_key_rock,
                              int (*get_key) (void *get_key_rock, int kvno,
                                      struct ktc_encryptionKey *
                                      serverKey),
                              int (*user_ok) (char *name, char *instance,
                                      char *cell, afs_int32 kvno))
{
    struct rx_securityClass *tsc;
    struct rxkad_sprivate *tsp;
    int size;

    rxkad_Init();

    if (!get_key)
        return 0;

    size = sizeof(struct rx_securityClass);
    tsc = rxi_Alloc(size);
    memset(tsc, 0, size);
    tsc->refCount = 1;		/* caller has one reference */
    tsc->ops = &rxkad_server_ops;
    size = sizeof(struct rxkad_sprivate);
    tsp = rxi_Alloc(size);
    memset(tsp, 0, size);
    tsc->privateData = (char *)tsp;

    tsp->type |= rxkad_server;	/* so can identify later */
    tsp->level = level;		/* level of encryption */
    tsp->get_key_rock = get_key_rock;
    tsp->get_key = get_key;	/* to get server ticket */
    tsp->user_ok = user_ok;	/* to inform server of client id. */
    init_random_int32();

    INC_RXKAD_STATS(serverObjects);
    return tsc;
}
Esempio n. 7
0
static void
do_handlesocketerror(osi_socket so)
{
#ifdef AFS_RXERRQ_ENV
    char *cmsgbuf;
    size_t cmsgbuf_len;

    cmsgbuf_len = 256;
    cmsgbuf = rxi_Alloc(cmsgbuf_len);
    if (!cmsgbuf) {
	return;
    }

    while (osi_HandleSocketError(so, cmsgbuf, cmsgbuf_len))
	;

    rxi_Free(cmsgbuf, cmsgbuf_len);
#endif
}
Esempio n. 8
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 = rx_GetSecurityData(aconn);
    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_enctype,
                              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, (char *)sconn->ivec, (char *)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 = rxi_Alloc(size);
        memset(rock, 0, size);
        rock->kvno = kvno;
        memcpy(&rock->client, &client, sizeof(rock->client));
        sconn->rock = rock;
    }
    return 0;
}
Esempio n. 9
0
/* Add the indicated event (function, arg) at the specified clock time */
struct rxevent *
rxevent_Post(struct clock * when, void (*func)(), void *arg, void *arg1)
/* when - When event should happen, in clock (clock.h) units */
{
    struct rxevent *ev, *qe, *qpr;

#ifdef RXDEBUG
    if (Log) {
	struct clock now;

	clock_GetTime(&now);
	fprintf(Log, "%ld.%ld: rxevent_Post(%ld.%ld, %p, %p)\n",
		now.sec, now.usec, when->sec, when->usec, func, arg);
    }
#endif
#if defined(AFS_SGIMP_ENV)
    ASSERT(osi_rxislocked());
#endif

    /*
     * If we're short on free event entries, create a block of new ones and
     * add them to the free queue
     */
    if (queue_IsEmpty(&rxevent_free)) {
	int i;

#if	defined(AFS_AIX32_ENV) && defined(KERNEL)
	ev = (struct rxevent *) rxi_Alloc(sizeof(struct rxevent));
	queue_Append(&rxevent_free, &ev[0]), rxevent_nFree++;
#else
	ev = (struct rxevent *) osi_Alloc(sizeof(struct rxevent) *
					  rxevent_allocUnit);
	xsp = xfreemallocs;
	xfreemallocs = (struct xfreelist *) ev;
	xfreemallocs->next = xsp;
	for (i = 0; i < rxevent_allocUnit; i++)
	    queue_Append(&rxevent_free, &ev[i]), rxevent_nFree++;
#endif
    }
    /* Grab and initialize a new rxevent structure */
    ev = queue_First(&rxevent_free, rxevent);
    queue_Remove(ev);
    rxevent_nFree--;

    /* Record user defined event state */
    ev->eventTime = *when;
    ev->func = func;
    ev->arg = arg;
    ev->arg1 = arg1;
    rxevent_nPosted += 1;	       /* Rather than ++, to shut high-C up
				        * regarding never-set variables */

    /*
     * Locate a slot for the new entry.  The queue is ordered by time, and we
     * assume that a new entry is likely to be greater than a majority of the
     * entries already on the queue (unless there's very few entries on the
     * queue), so we scan it backwards
     */
    for (queue_ScanBackwards(&rxevent_queue, qe, qpr, rxevent)) {
	if (clock_Ge(when, &qe->eventTime)) {
	    queue_InsertAfter(qe, ev);
	    return ev;
	}
    }
    /* The event is to expire earlier than any existing events */
    queue_Prepend(&rxevent_queue, ev);
    if (rxevent_ScheduledEarlierEvent)
	(*rxevent_ScheduledEarlierEvent) ();	/* Notify our external
						 * scheduler */
    return ev;
}