📄 rlm_jradius.c
字号:
return 0;}/* * Pack an array of bytes into a byte array buffer */static int pack_bytes(byte_array * ba, unsigned char *d, unsigned int dlen){ if (ba->left < dlen) return -1; memcpy((void *)(ba->b + ba->pos), d, dlen); ba->pos += dlen; ba->left -= dlen; return 0;}/* * Pack an integer into a byte array buffer (adjusting for byte-order) */static int pack_uint32(byte_array * ba, uint32_t i){ if (ba->left < 4) return -1; i = htonl(i); memcpy((void *)(ba->b + ba->pos), (void *)&i, 4); ba->pos += 4; ba->left -= 4; return 0;}/* * Pack one byte array buffer into another byte array buffer */static int pack_array(byte_array * ba, byte_array * a){ if (ba->left < a->pos) return -1; memcpy((void *)(ba->b + ba->pos), (void *)a->b, a->pos); ba->pos += a->pos; ba->left -= a->pos; return 0;}/* * Pack radius attributes into a byte array buffer */static int pack_vps(byte_array * ba, VALUE_PAIR * vps){ uint32_t i; VALUE_PAIR * vp; for (vp = vps; vp != NULL; vp = vp->next) { radlog(L_DBG, LOG_PREFIX "packing attribute %s (type: %d; len: %d)", vp->name, vp->attribute, vp->length); i = vp->attribute; /* element is int, not uint32_t */ if (pack_uint32(ba, i) == -1) return -1; i = vp->length; if (pack_uint32(ba, i) == -1) return -1; i = vp->operator; if (pack_uint32(ba, i) == -1) return -1; switch (vp->type) { case PW_TYPE_INTEGER: case PW_TYPE_DATE: if (pack_uint32(ba, vp->lvalue) == -1) return -1; break; case PW_TYPE_IPADDR: if (pack_bytes(ba, (void *)&vp->vp_ipaddr, vp->length) == -1) return -1; break; default: if (pack_bytes(ba, (void *)vp->vp_octets, vp->length) == -1) return -1; break; } } return 0;}/* * Pack a radius packet into a byte array buffer */static int pack_packet(byte_array * ba, RADIUS_PACKET * p){ /*unsigned char code = p->code;*/ unsigned char buff[HALF_MESSAGE_LEN]; byte_array pba; init_byte_array(&pba, buff, sizeof(buff)); if (pack_vps (&pba, p->vps) == -1) return -1; radlog(L_DBG, LOG_PREFIX "packing packet with code: %d (attr length: %d)", p->code, pba.pos); if (pack_byte (ba, p->code) == -1) return -1; if (pack_byte (ba, p->id) == -1) return -1; if (pack_uint32 (ba, pba.pos) == -1) return -1; if (pba.pos == 0) return 0; if (pack_array (ba, &pba) == -1) return -1; return 0;}static int pack_request(byte_array * ba, REQUEST *r){ unsigned char buff[HALF_MESSAGE_LEN]; byte_array pba; init_byte_array(&pba, buff, sizeof(buff)); if (pack_vps (&pba, r->config_items) == -1) return -1; if (pack_uint32 (ba, pba.pos) == -1) return -1; if (pba.pos == 0) return 0; if (pack_array (ba, &pba) == -1) return -1; return 0;}/* * Read a single byte from socket */static int read_byte(JRSOCK *jrsock, unsigned char *b){ return (read(jrsock->con.sock, b, 1) == 1) ? 0 : -1;}static void unpack_uint32(unsigned char *c, uint32_t *i){ uint32_t ii; memcpy((void *)&ii, c, 4); *i = ntohl(ii);}/* * Read an integer from the socket (adjusting for byte-order) */static int read_uint32(JRSOCK *jrsock, uint32_t *i){ uint32_t ii; if (read(jrsock->con.sock, &ii, 4) != 4) return -1; *i = ntohl(ii); return 0;}/* * Read a value-pair list from the socket */static int read_vps(JRSOCK *jrsock, VALUE_PAIR **pl, int plen){ VALUE_PAIR *vp; unsigned char buff[MESSAGE_LEN]; uint32_t alen, atype, aop; int rlen = 0; while (rlen < plen) { if (read_uint32 (jrsock, &atype) == -1) return -1; rlen += 4; if (read_uint32 (jrsock, &alen) == -1) return -1; rlen += 4; if (read_uint32 (jrsock, &aop) == -1) return -1; rlen += 4; radlog(L_DBG, LOG_PREFIX "reading attribute: type=%d; len=%d", atype, alen); if (alen >= sizeof(buff)) { radlog(L_ERR, LOG_PREFIX "packet value too large (len: %d)", alen); return -1; } if (read(jrsock->con.sock, buff, alen) != (int)alen) return -1; rlen += alen; buff[alen]=0; /* * Create new attribute */ vp = paircreate(atype, -1); vp->operator = aop; if (vp->type == -1) { /* * FreeRADIUS should know about the same attributes that JRadius knows */ radlog(L_ERR, LOG_PREFIX "received attribute we do not recognize (type: %d)", atype); pairbasicfree(vp); continue; } /* * Fill in the attribute value based on type */ switch (vp->type) { case PW_TYPE_INTEGER: case PW_TYPE_DATE: { unpack_uint32(buff, &vp->lvalue); vp->length = 4; } break; case PW_TYPE_IPADDR: memcpy((void *)&vp->vp_ipaddr, buff, 4); vp->length = 4; break; default: if (alen >= sizeof(vp->vp_octets)) alen = sizeof(vp->vp_octets) - 1; memcpy((void *)vp->vp_octets, buff, alen); vp->length = alen; break; } /* * Add the attribute to the packet */ pairadd(pl, vp); } return rlen;}/* * Read a radius packet from the socket */static int read_packet(JRADIUS * inst, JRSOCK *jrsock, RADIUS_PACKET *p){ unsigned char code; unsigned char id; unsigned int plen; if (read_byte (jrsock, &code) == -1) return -1; if (read_byte (jrsock, &id) == -1) return -1; if (read_uint32 (jrsock, &plen) == -1) return -1; radlog(L_DBG, LOG_PREFIX "reading packet: code=%d len=%d", (int)code, plen); if (inst->allow_codechange) if (code != p->code) { radlog(L_INFO, LOG_PREFIX "changing packet code from %d to %d", p->code, code); p->code = code; } if (inst->allow_idchange) if (id != p->id) { radlog(L_INFO, LOG_PREFIX "changing packet id from %d to %d", p->id, id); p->id = id; } /* * Delete previous attribute list */ pairfree(&p->vps); if (plen == 0) return 0; if (read_vps (jrsock, &p->vps, plen) == -1) return -1; return 0;}static int read_request(JRSOCK *jrsock, REQUEST *p){ unsigned int plen; if (read_uint32(jrsock, &plen) == -1) return -1; radlog(L_DBG, LOG_PREFIX "reading request: config_item: len=%d", plen); /* * Delete previous attribute list */ pairfree(&p->config_items); if (plen == 0) return 0; if (read_vps(jrsock, &p->config_items, plen) == -1) return -1; return 0;}static int rlm_jradius_call(char func, void *instance, REQUEST *req, int isproxy){ JRADIUS * inst = instance; RADIUS_PACKET * request = isproxy ? req->proxy : req->packet; RADIUS_PACKET * reply = isproxy ? req->proxy_reply : req->reply; JRSOCK * jrsock = 0; JRSOCK sjrsock; int exitstatus = inst->onfail; unsigned char rcode, pcount; unsigned char buff[MESSAGE_LEN]; byte_array ba; char * n = inst->name; unsigned int nlen = strlen(n); const char * err = 0; int rc, attempt2=0;#define W_ERR(s) { err=s; goto packerror; }#define R_ERR(s) { err=s; goto parseerror; } if (inst->keepalive) { jrsock = get_socket(inst); if (!jrsock) return exitstatus; } else { jrsock = &sjrsock; memset(jrsock, 0, sizeof(*jrsock)); jrsock->state = not_connected; } init_byte_array(&ba, buff, sizeof(buff)); pcount = 0; if (request) pcount++; if (reply) pcount++; /* * Create byte array to send to jradius */ if ((rc = pack_uint32 (&ba, nlen)) == -1) W_ERR("pack_uint32(nlen)"); if ((rc = pack_bytes (&ba, (void *)n, nlen)) == -1) W_ERR("pack_bytes(name)"); if ((rc = pack_byte (&ba, func)) == -1) W_ERR("pack_byte(fun)"); if ((rc = pack_byte (&ba, pcount)) == -1) W_ERR("pack_byte(pcnt)"); if (pcount > 0 && (rc = pack_packet (&ba, request)) == -1) W_ERR("pack_packet(req)"); if (pcount > 1 && (rc = pack_packet (&ba, reply)) == -1) W_ERR("pack_packet(rep)"); if ((rc = pack_request(&ba, req)) == -1) W_ERR("pack_request()"); /* * Send data */ start_over: if (jrsock->state == not_connected) { if (attempt2) radlog(L_ERR, LOG_PREFIX "reconnecting socket id %d", jrsock->id); if (!connect_socket(jrsock, inst)) { if (attempt2) radlog(L_ERR, LOG_PREFIX "could not reconnect socket %d, giving up", jrsock->id); goto cleanup; } } radlog(L_DBG, LOG_PREFIX "sending %d bytes to socket %d", ba.pos, jrsock->id); if (socket_send(jrsock, ba.b, ba.pos) != (int)ba.pos || (rc = read_byte (jrsock, &rcode)) == -1) { /* * With an error on the write or the first read, try closing the socket * and reconnecting to see if that improves matters any (tries this only once) */ radlog(L_ERR, LOG_PREFIX "error sending request with socket %d", jrsock->id); if (!inst->keepalive || attempt2) W_ERR("socket_send/first_read"); close_socket(inst, jrsock); attempt2 = 1; goto start_over; } /* * Read result */ if ((rc = read_byte (jrsock, &pcount)) == -1) R_ERR("read_byte(pcnt)"); radlog(L_DBG, LOG_PREFIX "return code %d; receiving %d packets", (int)rcode, (int)pcount); if (pcount > 0 && request) if ((rc = read_packet (inst, jrsock, request)) == -1) R_ERR("read_packet(req)"); if (pcount > 1 && reply) if ((rc = read_packet (inst, jrsock, reply)) == -1) R_ERR("read_packet(rep)"); if ((rc = read_request (jrsock, req)) == -1) R_ERR("read_request()"); /* * Since we deleted all the attribute lists in the request, * we need to reconfigure a few pointers in the REQUEST object */ if (req->username) { req->username = pairfind(request->vps, PW_USER_NAME); } if (req->password) { req->password = pairfind(request->vps, PW_PASSWORD); if (!req->password) req->password = pairfind(request->vps, PW_CHAP_PASSWORD); } /* * All done, set return code and cleanup */ exitstatus = (int)rcode; goto cleanup; parseerror: radlog(L_ERR, LOG_PREFIX "problem parsing the data [%s]",err); if (inst->keepalive) close_socket(inst, jrsock); goto cleanup; packerror: radlog(L_ERR, LOG_PREFIX "problem packing the data[%s]",err); if (inst->keepalive) close_socket(inst, jrsock); cleanup: if (inst->keepalive) release_socket(inst, jrsock); else close_socket(inst, jrsock); return exitstatus;}static int jradius_authenticate(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_authenticate, instance, request, 0);}static int jradius_authorize(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_authorize, instance, request, 0);}static int jradius_preacct(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_preacct, instance, request, 0);}static int jradius_accounting(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_accounting, instance, request, 0);}static int jradius_checksimul(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_checksimul, instance, request, 0);}static int jradius_pre_proxy(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_pre_proxy, instance, request, 1);}static int jradius_post_proxy(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_post_proxy, instance, request, 1);}static int jradius_post_auth(void *instance, REQUEST *request){ return rlm_jradius_call(JRADIUS_post_auth, instance, request, 0);}static int jradius_detach(void *instance){ JRADIUS *inst = (JRADIUS *) instance; free_socketpool(inst); free(inst); return 0;}module_t rlm_jradius = { RLM_MODULE_INIT, "jradius", RLM_TYPE_THREAD_SAFE, jradius_instantiate, jradius_detach, { jradius_authenticate, jradius_authorize, jradius_preacct, jradius_accounting, jradius_checksimul, jradius_pre_proxy, jradius_post_proxy, jradius_post_auth },};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -