📄 radeapclient.c
字号:
newvp = paircreate(ATTRIBUTE_EAP_SIM_KEY, PW_TYPE_OCTETS); memcpy(newvp->strvalue, eapsim_mk.K_aut, EAPSIM_AUTH_SIZE); newvp->length = EAPSIM_AUTH_SIZE; pairreplace(&(rep->vps), newvp); return 1;}/* * this code runs the EAP-SIM client state machine. * the *request* is from the server. * the *reponse* is to the server. * */static int respond_eap_sim(RADIUS_PACKET *req, RADIUS_PACKET *resp){ enum eapsim_clientstates state, newstate; enum eapsim_subtype subtype; VALUE_PAIR *vp, *statevp, *radstate, *eapid; char statenamebuf[32], subtypenamebuf[32]; if ((radstate = paircopy2(req->vps, PW_STATE)) == NULL) { return 0; } if ((eapid = paircopy2(req->vps, ATTRIBUTE_EAP_ID)) == NULL) { return 0; } /* first, dig up the state from the request packet, setting * outselves to be in EAP-SIM-Start state if there is none. */ if((statevp = pairfind(resp->vps, ATTRIBUTE_EAP_SIM_STATE)) == NULL) { /* must be initial request */ statevp = paircreate(ATTRIBUTE_EAP_SIM_STATE, PW_TYPE_INTEGER); statevp->lvalue = eapsim_client_init; pairreplace(&(resp->vps), statevp); } state = statevp->lvalue; /* * map the attributes, and authenticate them. */ unmap_eapsim_types(req); printf("<+++ EAP-sim decoded packet:\n"); vp_printlist(stdout, req->vps); if((vp = pairfind(req->vps, ATTRIBUTE_EAP_SIM_SUBTYPE)) == NULL) { return 0; } subtype = vp->lvalue; /* * look for the appropriate state, and process incoming message */ switch(state) { case eapsim_client_init: switch(subtype) { case eapsim_start: newstate = process_eap_start(req, resp); break; case eapsim_challenge: case eapsim_notification: case eapsim_reauth: default: fprintf(stderr, "radeapclient: sim in state %s message %s is illegal. Reply dropped.\n", sim_state2name(state, statenamebuf, sizeof(statenamebuf)), sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); /* invalid state, drop message */ return 0; } break; case eapsim_client_start: switch(subtype) { case eapsim_start: /* NOT SURE ABOUT THIS ONE, retransmit, I guess */ newstate = process_eap_start(req, resp); break; case eapsim_challenge: newstate = process_eap_challenge(req, resp); break; default: fprintf(stderr, "radeapclient: sim in state %s message %s is illegal. Reply dropped.\n", sim_state2name(state, statenamebuf, sizeof(statenamebuf)), sim_subtype2name(subtype, subtypenamebuf, sizeof(subtypenamebuf))); /* invalid state, drop message */ return 0; } break; default: fprintf(stderr, "radeapclient: sim in illegal state %s\n", sim_state2name(state, statenamebuf, sizeof(statenamebuf))); return 0; } /* copy the eap state object in */ pairreplace(&(resp->vps), eapid); /* update stete info, and send new packet */ map_eapsim_types(resp); /* copy the radius state object in */ pairreplace(&(resp->vps), radstate); statevp->lvalue = newstate; return 1;}static int respond_eap_md5(RADIUS_PACKET *req, RADIUS_PACKET *rep){ VALUE_PAIR *vp, *id, *state; int valuesize, namesize; unsigned char identifier; unsigned char *value; unsigned char *name; MD5_CTX context; char response[16]; cleanresp(rep); if ((state = paircopy2(req->vps, PW_STATE)) == NULL) { fprintf(stderr, "radeapclient: no state attribute found\n"); return 0; } if ((id = paircopy2(req->vps, ATTRIBUTE_EAP_ID)) == NULL) { fprintf(stderr, "radeapclient: no EAP-ID attribute found\n"); return 0; } identifier = id->lvalue; if ((vp = pairfind(req->vps, ATTRIBUTE_EAP_BASE+PW_EAP_MD5)) == NULL) { fprintf(stderr, "radeapclient: no EAP-MD5 attribute found\n"); return 0; } /* got the details of the MD5 challenge */ valuesize = vp->strvalue[0]; value = &vp->strvalue[1]; name = &vp->strvalue[valuesize+1]; namesize = vp->length - (valuesize + 1); /* sanitize items */ if(valuesize > vp->length) { fprintf(stderr, "radeapclient: md5 valuesize if too big (%d > %d)\n", valuesize, vp->length); return 0; } /* now do the CHAP operation ourself, rather than build the * buffer. We could also call rad_chap_encode, but it wants * a CHAP-Challenge, which we don't want to bother with. */ librad_MD5Init(&context); librad_MD5Update(&context, &identifier, 1); librad_MD5Update(&context, password, strlen(password)); librad_MD5Update(&context, value, valuesize); librad_MD5Final(response, &context); vp = paircreate(ATTRIBUTE_EAP_BASE+PW_EAP_MD5, PW_TYPE_OCTETS); vp->strvalue[0]=16; memcpy(&vp->strvalue[1], response, 16); vp->length = 17; pairreplace(&(rep->vps), vp); pairreplace(&(rep->vps), id); /* copy the state object in */ pairreplace(&(rep->vps), state); 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, 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 = '\0'; } 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;}int main(int argc, char **argv){ RADIUS_PACKET *req; char *p; int c; int port = 0; char *filename = NULL; FILE *fp; int count = 1; int id; id = ((int)getpid() & 0xff); librad_debug = 0; radlog_dest = RADLOG_STDERR; while ((c = getopt(argc, argv, "c:d:f:hi:qst:r:S:xXv")) != EOF) { switch(c) { case 'c': if (!isdigit((int) *optarg)) usage(); count = atoi(optarg); break; case 'd': radius_dir = optarg; break; case 'f': filename = optarg; break; case 'q': do_output = 0; break; case 'x': debug_flag++; librad_debug++; break; case 'X': sha1_data_problems = 1; break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); break; case 'i': if (!isdigit((int) *optarg)) usage(); id = atoi(optarg); if ((id < 0) || (id > 255)) { usage(); } break; case 's': do_summary = 1; break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("radclient: $Id: radeapclient.c,v 1.7 2004/02/26 19:04:29 aland Exp $ built on " __DATE__ " at " __TIME__ "\n"); exit(0); break; case 'S': fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", optarg, strerror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { fprintf(stderr, "radclient: Error reading %s: %s\n", optarg, strerror(errno)); exit(1); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { fprintf(stderr, "radclient: Secret in %s is too short\n", optarg); exit(1); } secret = filesecret; break; case 'h': default: usage(); break; } } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((secret == NULL) && (argc < 4))) { usage(); } if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) { librad_perror("radclient"); return 1; } if ((req = rad_alloc(1)) == NULL) { librad_perror("radclient"); exit(1); }#if 0 { FILE *randinit; if((randinit = fopen("/dev/urandom", "r")) == NULL) { perror("/dev/urandom"); } else { fread(randctx.randrsl, 256, 1, randinit); fclose(randinit); } } lrad_randinit(&randctx, 1);#endif req->id = id; /* * Strip port from hostname if needed. */ if ((p = strchr(argv[1], ':')) != NULL) { *p++ = 0; port = atoi(p); } /* * See what kind of request we want to send. */ if (strcmp(argv[2], "auth") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_AUTHENTICATION_REQUEST; } else if (strcmp(argv[2], "acct") == 0) { if (port == 0) port = getport("radacct"); if (port == 0) port = PW_ACCT_UDP_PORT; req->code = PW_ACCOUNTING_REQUEST; do_summary = 0; } else if (strcmp(argv[2], "status") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_STATUS_SERVER; } else if (strcmp(argv[2], "disconnect") == 0) { if (port == 0) port = PW_POD_UDP_PORT; req->code = PW_DISCONNECT_REQUEST; } else if (isdigit((int) argv[2][0])) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = atoi(argv[2]); } else { usage(); } /* * Ensure that the configuration is initialized. */ memset(&mainconfig, 0, sizeof(mainconfig)); /* * Resolve hostname. */ req->dst_port = port; req->dst_ipaddr = ip_getaddr(argv[1]); if (req->dst_ipaddr == INADDR_NONE) { fprintf(stderr, "radclient: Failed to find IP address for host %s\n", argv[1]); exit(1); } /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * Read valuepairs. * Maybe read them, from stdin, if there's no * filename, or if the filename is '-'. */ if (filename && (strcmp(filename, "-") != 0)) { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", filename, strerror(errno)); exit(1); } } else { fp = stdin; } /* * Send request. */ if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("radclient: socket: "); exit(1); } while(!filedone) { if(req->vps) pairfree(&req->vps); if ((req->vps = readvp2(fp, &filedone, "radeapclient:")) == NULL) { break; } sendrecv_eap(req); } if(do_summary) { printf("\n\t Total approved auths: %d\n", totalapp); printf("\t Total denied auths: %d\n", totaldeny); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -