Пример #1
0
/* 
 * verify = MD5(id+password+challenge_sent)
 */
int eapmd5_verify(MD5_PACKET *packet, VALUE_PAIR* password, 
		md5_packet_t *challenge)
{
	char	*ptr;
	char	string[MAX_STRING_LEN*2];
	unsigned char output[MAX_STRING_LEN];
	unsigned short len;

	if ((password == NULL) || (challenge == NULL)) {
		return 0;
	}

	/*
	 *	Sanity check it.
	 */
	if (packet->value_size != 16) {
		radlog(L_ERR, "rlm_eap_md5: Expected 16 bytes of response to challenge, got %d", packet->value_size);
		return 0;
	}

	len = 0;
	ptr = string;

	*ptr++ = packet->id;
	len++;
	memcpy(ptr, password->strvalue, password->length);
	ptr += password->length;
	len += password->length;

	memcpy(ptr, challenge->value_name, challenge->value_size);
	len += challenge->value_size;

	librad_md5_calc((u_char *)output, (u_char *)string, len);

	/*
	 *	The length of the response is always 16 for MD5.
	 */
	if (memcmp(output, packet->value, 16) != 0) {
		return 0;
	}
	return 1;
}
Пример #2
0
/*
 *	Compare two RADIUS_PACKET data structures, based on a number
 *	of criteria.
 */
static int send_one_packet(radclient_t *radclient)
{
    int i;

    assert(radclient->done == 0);

    /*
     *	Remember when we have to wake up, to re-send the
     *	request, of we didn't receive a response.
     */
    if ((sleep_time == -1) ||
            (sleep_time > (int) timeout))
    {
        sleep_time = (int) timeout;
    }

    /*
     *	Haven't sent the packet yet.  Initialize it.
     */
    if (radclient->request->id == -1)
    {
        int found = 0;

        assert(radclient->reply == NULL);

        /*
         *	Find a free packet Id
         */
        for (i = 0; i < 256; i++)
        {
            if (radius_id[(last_used_id + i) & 0xff] == 0)
            {
                last_used_id = (last_used_id + i) & 0xff;
                radius_id[last_used_id] = 1;
                radclient->request->id = last_used_id++;
                found = 1;
                break;
            }
        }

        /*
         *	Didn't find a free packet ID, we're not done,
         *	we don't sleep, and we stop trying to process
         *	this packet.
         */
        if (!found)
        {
            done = 0;
            sleep_time = 0;
            return 0;
        }

        assert(radclient->request->id != -1);
        assert(radclient->request->data == NULL);

        librad_md5_calc(radclient->request->vector, radclient->request->vector,
                        sizeof(radclient->request->vector));

        /*
         *	Update the password, so it can be encrypted with the
         *	new authentication vector.
         */
        if (radclient->password[0] != '\0')
        {
            VALUE_PAIR *vp;

            if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL)
            {
                strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
                vp->length = strlen(vp->strvalue);

            }
            else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL)
            {
                strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
                vp->length = strlen(vp->strvalue);

                rad_chap_encode(radclient->request, (char *) vp->strvalue, radclient->request->id, vp);
                vp->length = 17;
            }
        }

        radclient->timestamp = time(NULL);
        radclient->tries = 1;
        radclient->resend++;

        /*
         *	Duplicate found.  Serious error!
         */
    }
    else  		/* radclient->request->id >= 0 */
    {
        time_t now = time(NULL);

        /*
         *	FIXME: Accounting packets are never retried!
         *	The Acct-Delay-Time attribute is updated to
         *	reflect the delay, and the packet is re-sent
         *	from scratch!
         */

        /*
         *	Not time for a retry, do so.
         */
        if ((now - radclient->timestamp) < timeout)
        {
            /*
             *	When we walk over the tree sending
             *	packets, we update the minimum time
             *	required to sleep.
             */
            if ((sleep_time == -1) ||
                    (sleep_time > (now - radclient->timestamp)))
            {
                sleep_time = now - radclient->timestamp;
            }
            return 0;
        }

        /*
         *	We're not trying later, maybe the packet is done.
         */
        if (radclient->tries == retries)
        {
            assert(radclient->request->id >= 0);

            /*
             *	Delete the request from the tree of
             *	outstanding requests.
             */

            fprintf(stderr, "radclient: no response from server for ID %d\n", radclient->request->id);
            /*
             *	Normally we mark it "done" when we've received
             *	the response, but this is a special case.
             */
            if (radclient->resend == resend_count)
            {
                radclient->done = 1;
            }
            totallost++;
            return -1;
        }

        /*
         *	We are trying later.
         */
        radclient->timestamp = now;
        radclient->tries++;
    }


    /*
     *	Send the packet.
     */
    if (rad_send(radclient->request, NULL, secret) < 0)
    {
        fprintf(stderr, "radclient: Failed to send packet for ID %d: %s\n",
                radclient->request->id, librad_errstr);
    }

    return 0;
}
Пример #3
0
static int sendrecv_eap(RADIUS_PACKET *rep)
{
	RADIUS_PACKET *req = NULL;
	VALUE_PAIR *vp, *vpnext;
	int tried_eap_md5 = 0;

	/*
	 *	Keep a copy of the the User-Password attribute.
	 */
	if ((vp = pairfind(rep->vps, ATTRIBUTE_EAP_MD5_PASSWORD)) != NULL) {
		strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));

	} else 	if ((vp = pairfind(rep->vps, PW_PASSWORD)) != NULL) {
		strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));
		/*
		 *	Otherwise keep a copy of the CHAP-Password attribute.
		 */
	} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) {
		strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));
	} else {
		*password = '******';
	}

 again:
	rep->id++;

	printf("\n+++> About to send encoded packet:\n");
	vp_printlist(stdout, rep->vps);

	/*
	 * if there are EAP types, encode them into an EAP-Message
	 *
	 */
	map_eap_types(rep);

	/*
	 *  Fix up Digest-Attributes issues
	 */
	for (vp = rep->vps; vp != NULL; vp = vp->next) {
		switch (vp->attribute) {
		default:
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
			memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
			vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
			vp->length += 2;
			vp->strvalue[1] = vp->length;
			vp->attribute = PW_DIGEST_ATTRIBUTES;
			break;
		}
	}

	/*
	 *	If we've already sent a packet, free up the old
	 *	one, and ensure that the next packet has a unique
	 *	ID and authentication vector.
	 */
	if (rep->data) {
		free(rep->data);
		rep->data = NULL;
	}

	librad_md5_calc(rep->vector, rep->vector,
			sizeof(rep->vector));

	if (*password != '\0') {
		if ((vp = pairfind(rep->vps, PW_PASSWORD)) != NULL) {
			strNcpy((char *)vp->strvalue, password, strlen(password) + 1);
			vp->length = strlen(password);

		} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) {
			strNcpy((char *)vp->strvalue, password, strlen(password) + 1);
			vp->length = strlen(password);

			rad_chap_encode(rep, (char *) vp->strvalue, rep->id, vp);
			vp->length = 17;
		}
	} /* there WAS a password */

	/* send the response, wait for the next request */
	send_packet(rep, &req);

	/* okay got back the packet, go and decode the EAP-Message. */
	unmap_eap_types(req);

	printf("<+++ EAP decoded packet:\n");
	vp_printlist(stdout, req->vps);

	/* now look for the code type. */
	for (vp = req->vps; vp != NULL; vp = vpnext) {
		vpnext = vp->next;

		switch (vp->attribute) {
		default:
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_MD5:
			if(respond_eap_md5(req, rep) && tried_eap_md5 < 3)
			{
				tried_eap_md5++;
				goto again;
			}
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_SIM:
			if(respond_eap_sim(req, rep))
			{
				goto again;
			}
			break;
		}
	}

	return 1;
}