main(int argc, char *argv[]) { int filedone; RADIUS_PACKET *req,*req2; VALUE_PAIR *vp, *vpkey, *vpextra; extern unsigned int sha1_data_problems; req = NULL; req2 = NULL; filedone = 0; if(argc>1) { sha1_data_problems = 1; } if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radclient"); return 1; } req = rad_alloc(NULL, 1) if (!req) { fr_perror("radclient"); exit(1); } req2 = rad_alloc(NULL, 1); if (!req2) { fr_perror("radclient"); exit(1); } while(!filedone) { if (req->vps) pairfree(&req->vps); if (req2->vps) pairfree(&req2->vps); if (readvp2(&req->vps, NULL, stdin, &filedone) < 0) { fr_perror("radeapclient"); break; } if (fr_debug_flag > 1) { printf("\nRead:\n"); vp_printlist(stdout, req->vps); } map_eapsim_types(req); map_eap_methods(req); if (fr_debug_flag > 1) { printf("Mapped to:\n"); vp_printlist(stdout, req->vps); } /* find the EAP-Message, copy it to req2 */ vp = paircopy2(NULL, req->vps, PW_EAP_MESSAGE, 0, TAG_ANY); if(!vp) continue; pairadd(&req2->vps, vp); /* only call unmap for sim types here */ unmap_eap_methods(req2); unmap_eapsim_types(req2); if (fr_debug_flag > 1) { printf("Unmapped to:\n"); vp_printlist(stdout, req2->vps); } vp = pairfind(req2->vps, ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_MAC, 0, TAG_ANY); vpkey = pairfind(req->vps, ATTRIBUTE_EAP_SIM_KEY, 0, TAG_ANY); vpextra = pairfind(req->vps, ATTRIBUTE_EAP_SIM_EXTRA, 0, TAG_ANY); if(vp != NULL && vpkey != NULL && vpextra!=NULL) { uint8_t calcmac[16]; /* find the EAP-Message, copy it to req2 */ memset(calcmac, 0, sizeof(calcmac)); printf("Confirming MAC..."); if(eapsim_checkmac(req2->vps, vpkey->vp_strvalue, vpextra->vp_strvalue, vpextra->length, calcmac)) { printf("succeed\n"); } else { int i, j; printf("calculated MAC ("); for (i = 0; i < 20; i++) { if(j==4) { printf("_"); j=0; } j++; printf("%02x", calcmac[i]); } printf(" did not match\n"); } } fflush(stdout); } }
static int sendrecv_eap(RADIUS_PACKET *rep) { RADIUS_PACKET *req = NULL; VALUE_PAIR *vp, *vpnext; int tried_eap_md5 = 0; if (!rep) return -1; /* * Keep a copy of the the User-Password attribute. */ if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); /* * Otherwise keep a copy of the CHAP-Password attribute. */ } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, vp->vp_strvalue, sizeof(password)); } else { *password = '******'; } again: rep->id++; /* * if there are EAP types, encode them into an EAP-Message * */ map_eap_methods(rep); /* * Fix up Digest-Attributes issues */ for (vp = rep->vps; vp != NULL; vp = vp->next) { switch (vp->da->attr) { 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! */ { DICT_ATTR const *da; uint8_t *p, *q; p = talloc_array(vp, uint8_t, vp->length + 2); memcpy(p + 2, vp->vp_octets, vp->length); p[0] = vp->da->attr - PW_DIGEST_REALM + 1; vp->length += 2; p[1] = vp->length; da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0); vp->da = da; /* * Re-do pairmemsteal ourselves, * because we play games with * vp->da, and pairmemsteal goes * to GREAT lengths to sanitize * and fix and change and * double-check the various * fields. */ memcpy(&q, &vp->vp_octets, sizeof(q)); talloc_free(q); vp->vp_octets = talloc_steal(vp, p); vp->type = VT_DATA; VERIFY_VP(vp); } 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) { talloc_free(rep->data); rep->data = NULL; } fr_md5_calc(rep->vector, rep->vector, sizeof(rep->vector)); if (*password != '\0') { if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); uint8_t *p; p = talloc_zero_array(vp, uint8_t, 17); rad_chap_encode(rep, p, rep->id, vp); pairmemsteal(vp, p); } } /* there WAS a password */ /* send the response, wait for the next request */ send_packet(rep, &req); if (!req) return -1; /* okay got back the packet, go and decode the EAP-Message. */ unmap_eap_methods(req); debug_packet(req, R_RECV); /* now look for the code type. */ for (vp = req->vps; vp != NULL; vp = vpnext) { vpnext = vp->next; switch (vp->da->attr) { 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; }
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, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); /* * Otherwise keep a copy of the CHAP-Password attribute. */ } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue)); } else { *password = '******'; } again: rep->id++; /* * if there are EAP types, encode them into an EAP-Message * */ map_eap_methods(rep); /* * Fix up Digest-Attributes issues */ for (vp = rep->vps; vp != NULL; vp = vp->next) { switch (vp->da->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->vp_strvalue[2], &vp->vp_octets[0], vp->length); vp->vp_octets[0] = vp->da->attribute - PW_DIGEST_REALM + 1; vp->length += 2; vp->vp_octets[1] = vp->length; vp->da->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) { talloc_free(rep->data); rep->data = NULL; } fr_md5_calc(rep->vector, rep->vector, sizeof(rep->vector)); if (*password != '\0') { if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) { pairstrcpy(vp, password); rad_chap_encode(rep, vp->vp_octets, 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_methods(req); debug_packet(req, R_RECV); /* now look for the code type. */ for (vp = req->vps; vp != NULL; vp = vpnext) { vpnext = vp->next; switch (vp->da->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; }