radlib.c (c5384974d99d960de4e92f8a2cc1e3ad10aa6248) radlib.c (3fc0b61c51969c20551372e9c4adb4943e96dbd3)
1/*-
2 * Copyright 1998 Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 89 unchanged lines hidden (view full) ---

98 unsigned char md5[MD5_DIGEST_LENGTH];
99 const struct rad_server *srvp;
100 int padded_len;
101 int pos;
102
103 srvp = &h->servers[srv];
104 padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
105
1/*-
2 * Copyright 1998 Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 89 unchanged lines hidden (view full) ---

98 unsigned char md5[MD5_DIGEST_LENGTH];
99 const struct rad_server *srvp;
100 int padded_len;
101 int pos;
102
103 srvp = &h->servers[srv];
104 padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
105
106 memcpy(md5, &h->request[POS_AUTH], LEN_AUTH);
106 memcpy(md5, &h->out[POS_AUTH], LEN_AUTH);
107 for (pos = 0; pos < padded_len; pos += 16) {
108 int i;
109
110 /* Calculate the new scrambler */
111 MD5Init(&ctx);
112 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
113 MD5Update(&ctx, md5, 16);
114 MD5Final(md5, &ctx);
115
116 /*
117 * Mix in the current chunk of the password, and copy
118 * the result into the right place in the request. Also
119 * modify the scrambler in place, since we will use this
120 * in calculating the scrambler for next time.
121 */
122 for (i = 0; i < 16; i++)
107 for (pos = 0; pos < padded_len; pos += 16) {
108 int i;
109
110 /* Calculate the new scrambler */
111 MD5Init(&ctx);
112 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
113 MD5Update(&ctx, md5, 16);
114 MD5Final(md5, &ctx);
115
116 /*
117 * Mix in the current chunk of the password, and copy
118 * the result into the right place in the request. Also
119 * modify the scrambler in place, since we will use this
120 * in calculating the scrambler for next time.
121 */
122 for (i = 0; i < 16; i++)
123 h->request[h->pass_pos + pos + i] =
123 h->out[h->pass_pos + pos + i] =
124 md5[i] ^= h->pass[pos + i];
125 }
126}
127
128static void
124 md5[i] ^= h->pass[pos + i];
125 }
126}
127
128static void
129insert_request_authenticator(struct rad_handle *h, int srv)
129insert_request_authenticator(struct rad_handle *h, int resp)
130{
131 MD5_CTX ctx;
132 const struct rad_server *srvp;
133
130{
131 MD5_CTX ctx;
132 const struct rad_server *srvp;
133
134 srvp = &h->servers[srv];
134 srvp = &h->servers[h->srv];
135
136 /* Create the request authenticator */
137 MD5Init(&ctx);
135
136 /* Create the request authenticator */
137 MD5Init(&ctx);
138 MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
139 MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
140 MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
138 MD5Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
139 if (resp)
140 MD5Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
141 else
142 MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
143 MD5Update(&ctx, &h->out[POS_ATTRS], h->out_len - POS_ATTRS);
141 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
144 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
142 MD5Final(&h->request[POS_AUTH], &ctx);
145 MD5Final(&h->out[POS_AUTH], &ctx);
143}
144
145static void
146}
147
148static void
146insert_message_authenticator(struct rad_handle *h, int srv)
149insert_message_authenticator(struct rad_handle *h, int resp)
147{
148#ifdef WITH_SSL
149 u_char md[EVP_MAX_MD_SIZE];
150 u_int md_len;
151 const struct rad_server *srvp;
152 HMAC_CTX ctx;
150{
151#ifdef WITH_SSL
152 u_char md[EVP_MAX_MD_SIZE];
153 u_int md_len;
154 const struct rad_server *srvp;
155 HMAC_CTX ctx;
153 srvp = &h->servers[srv];
156 srvp = &h->servers[h->srv];
154
155 if (h->authentic_pos != 0) {
156 HMAC_CTX_init(&ctx);
157 HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
157
158 if (h->authentic_pos != 0) {
159 HMAC_CTX_init(&ctx);
160 HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
158 HMAC_Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
159 HMAC_Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
160 HMAC_Update(&ctx, &h->request[POS_ATTRS],
161 h->req_len - POS_ATTRS);
161 HMAC_Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
162 if (resp)
163 HMAC_Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
164 else
165 HMAC_Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
166 HMAC_Update(&ctx, &h->out[POS_ATTRS],
167 h->out_len - POS_ATTRS);
162 HMAC_Final(&ctx, md, &md_len);
163 HMAC_CTX_cleanup(&ctx);
164 HMAC_cleanup(&ctx);
168 HMAC_Final(&ctx, md, &md_len);
169 HMAC_CTX_cleanup(&ctx);
170 HMAC_cleanup(&ctx);
165 memcpy(&h->request[h->authentic_pos + 2], md, md_len);
171 memcpy(&h->out[h->authentic_pos + 2], md, md_len);
166 }
167#endif
168}
169
170/*
171 * Return true if the current response is valid for a request to the
172 * specified server.
173 */

--- 16 unchanged lines hidden (view full) ---

190
191 /* Check the source address */
192 if (from->sin_family != srvp->addr.sin_family ||
193 from->sin_addr.s_addr != srvp->addr.sin_addr.s_addr ||
194 from->sin_port != srvp->addr.sin_port)
195 return 0;
196
197 /* Check the message length */
172 }
173#endif
174}
175
176/*
177 * Return true if the current response is valid for a request to the
178 * specified server.
179 */

--- 16 unchanged lines hidden (view full) ---

196
197 /* Check the source address */
198 if (from->sin_family != srvp->addr.sin_family ||
199 from->sin_addr.s_addr != srvp->addr.sin_addr.s_addr ||
200 from->sin_port != srvp->addr.sin_port)
201 return 0;
202
203 /* Check the message length */
198 if (h->resp_len < POS_ATTRS)
204 if (h->in_len < POS_ATTRS)
199 return 0;
205 return 0;
200 len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
201 if (len > h->resp_len)
206 len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
207 if (len > h->in_len)
202 return 0;
203
204 /* Check the response authenticator */
205 MD5Init(&ctx);
208 return 0;
209
210 /* Check the response authenticator */
211 MD5Init(&ctx);
206 MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
207 MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
208 MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
212 MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
213 MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
214 MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
209 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
210 MD5Final(md5, &ctx);
215 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
216 MD5Final(md5, &ctx);
211 if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
217 if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
212 return 0;
213
214#ifdef WITH_SSL
215 /*
216 * For non accounting responses check the message authenticator,
217 * if any.
218 */
218 return 0;
219
220#ifdef WITH_SSL
221 /*
222 * For non accounting responses check the message authenticator,
223 * if any.
224 */
219 if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
225 if (h->in[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
220
226
221 memcpy(resp, h->response, MSGSIZE);
227 memcpy(resp, h->in, MSGSIZE);
222 pos = POS_ATTRS;
223
224 /* Search and verify the Message-Authenticator */
225 while (pos < len - 2) {
226
228 pos = POS_ATTRS;
229
230 /* Search and verify the Message-Authenticator */
231 while (pos < len - 2) {
232
227 if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
233 if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
228 /* zero fill the Message-Authenticator */
229 memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
230
231 HMAC_CTX_init(&hctx);
232 HMAC_Init(&hctx, srvp->secret,
233 strlen(srvp->secret), EVP_md5());
234 /* zero fill the Message-Authenticator */
235 memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
236
237 HMAC_CTX_init(&hctx);
238 HMAC_Init(&hctx, srvp->secret,
239 strlen(srvp->secret), EVP_md5());
234 HMAC_Update(&hctx, &h->response[POS_CODE],
240 HMAC_Update(&hctx, &h->in[POS_CODE],
235 POS_AUTH - POS_CODE);
241 POS_AUTH - POS_CODE);
236 HMAC_Update(&hctx, &h->request[POS_AUTH],
242 HMAC_Update(&hctx, &h->out[POS_AUTH],
237 LEN_AUTH);
238 HMAC_Update(&hctx, &resp[POS_ATTRS],
243 LEN_AUTH);
244 HMAC_Update(&hctx, &resp[POS_ATTRS],
239 h->resp_len - POS_ATTRS);
245 h->in_len - POS_ATTRS);
240 HMAC_Final(&hctx, md, &md_len);
241 HMAC_CTX_cleanup(&hctx);
242 HMAC_cleanup(&hctx);
246 HMAC_Final(&hctx, md, &md_len);
247 HMAC_CTX_cleanup(&hctx);
248 HMAC_cleanup(&hctx);
243 if (memcmp(md, &h->response[pos + 2],
249 if (memcmp(md, &h->in[pos + 2],
244 MD5_DIGEST_LENGTH) != 0)
245 return 0;
246 break;
247 }
250 MD5_DIGEST_LENGTH) != 0)
251 return 0;
252 break;
253 }
248 pos += h->response[pos + 1];
254 pos += h->in[pos + 1];
249 }
250 }
251#endif
252 return 1;
253}
254
255 }
256 }
257#endif
258 return 1;
259}
260
261/*
262 * Return true if the current request is valid for the specified server.
263 */
255static int
264static int
265is_valid_request(struct rad_handle *h)
266{
267 MD5_CTX ctx;
268 unsigned char md5[MD5_DIGEST_LENGTH];
269 const struct rad_server *srvp;
270 int len;
271#ifdef WITH_SSL
272 HMAC_CTX hctx;
273 u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
274 u_int md_len;
275 int pos;
276#endif
277
278 srvp = &h->servers[h->srv];
279
280 /* Check the message length */
281 if (h->in_len < POS_ATTRS)
282 return (0);
283 len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
284 if (len > h->in_len)
285 return (0);
286
287 if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
288 uint32_t zeroes[4] = { 0, 0, 0, 0 };
289 /* Check the request authenticator */
290 MD5Init(&ctx);
291 MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
292 MD5Update(&ctx, zeroes, LEN_AUTH);
293 MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
294 MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
295 MD5Final(md5, &ctx);
296 if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
297 return (0);
298 }
299
300#ifdef WITH_SSL
301 /* Search and verify the Message-Authenticator */
302 pos = POS_ATTRS;
303 while (pos < len - 2) {
304 if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
305 memcpy(resp, h->in, MSGSIZE);
306 /* zero fill the Request-Authenticator */
307 if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
308 memset(&resp[POS_AUTH], 0, LEN_AUTH);
309 /* zero fill the Message-Authenticator */
310 memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
311
312 HMAC_CTX_init(&hctx);
313 HMAC_Init(&hctx, srvp->secret,
314 strlen(srvp->secret), EVP_md5());
315 HMAC_Update(&hctx, resp, h->in_len);
316 HMAC_Final(&hctx, md, &md_len);
317 HMAC_CTX_cleanup(&hctx);
318 HMAC_cleanup(&hctx);
319 if (memcmp(md, &h->in[pos + 2],
320 MD5_DIGEST_LENGTH) != 0)
321 return (0);
322 break;
323 }
324 pos += h->in[pos + 1];
325 }
326#endif
327 return (1);
328}
329
330static int
256put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
257{
258 int padded_len;
259 int pad_len;
260
261 if (h->pass_pos != 0) {
262 generr(h, "Multiple User-Password attributes specified");
263 return -1;

--- 4 unchanged lines hidden (view full) ---

268 pad_len = padded_len - len;
269
270 /*
271 * Put in a place-holder attribute containing all zeros, and
272 * remember where it is so we can fill it in later.
273 */
274 clear_password(h);
275 put_raw_attr(h, type, h->pass, padded_len);
331put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
332{
333 int padded_len;
334 int pad_len;
335
336 if (h->pass_pos != 0) {
337 generr(h, "Multiple User-Password attributes specified");
338 return -1;

--- 4 unchanged lines hidden (view full) ---

343 pad_len = padded_len - len;
344
345 /*
346 * Put in a place-holder attribute containing all zeros, and
347 * remember where it is so we can fill it in later.
348 */
349 clear_password(h);
350 put_raw_attr(h, type, h->pass, padded_len);
276 h->pass_pos = h->req_len - padded_len;
351 h->pass_pos = h->out_len - padded_len;
277
278 /* Save the cleartext password, padded as necessary */
279 memcpy(h->pass, value, len);
280 h->pass_len = len;
281 memset(h->pass + len, 0, pad_len);
282 return 0;
283}
284
285static int
286put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
287{
288 if (len > 253) {
289 generr(h, "Attribute too long");
290 return -1;
291 }
352
353 /* Save the cleartext password, padded as necessary */
354 memcpy(h->pass, value, len);
355 h->pass_len = len;
356 memset(h->pass + len, 0, pad_len);
357 return 0;
358}
359
360static int
361put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
362{
363 if (len > 253) {
364 generr(h, "Attribute too long");
365 return -1;
366 }
292 if (h->req_len + 2 + len > MSGSIZE) {
367 if (h->out_len + 2 + len > MSGSIZE) {
293 generr(h, "Maximum message length exceeded");
294 return -1;
295 }
368 generr(h, "Maximum message length exceeded");
369 return -1;
370 }
296 h->request[h->req_len++] = type;
297 h->request[h->req_len++] = len + 2;
298 memcpy(&h->request[h->req_len], value, len);
299 h->req_len += len;
371 h->out[h->out_len++] = type;
372 h->out[h->out_len++] = len + 2;
373 memcpy(&h->out[h->out_len], value, len);
374 h->out_len += len;
300 return 0;
301}
302
303int
304rad_add_server(struct rad_handle *h, const char *host, int port,
305 const char *secret, int timeout, int tries)
306{
307 struct rad_server *srvp;

--- 210 unchanged lines hidden (view full) ---

518 * > 0 Success
519 */
520int
521rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
522 struct timeval *tv)
523{
524 int n;
525
375 return 0;
376}
377
378int
379rad_add_server(struct rad_handle *h, const char *host, int port,
380 const char *secret, int timeout, int tries)
381{
382 struct rad_server *srvp;

--- 210 unchanged lines hidden (view full) ---

593 * > 0 Success
594 */
595int
596rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
597 struct timeval *tv)
598{
599 int n;
600
601 if (h->type == RADIUS_SERVER) {
602 generr(h, "denied function call");
603 return (-1);
604 }
526 if (selected) {
527 struct sockaddr_in from;
528 socklen_t fromlen;
529
530 fromlen = sizeof from;
605 if (selected) {
606 struct sockaddr_in from;
607 socklen_t fromlen;
608
609 fromlen = sizeof from;
531 h->resp_len = recvfrom(h->fd, h->response,
610 h->in_len = recvfrom(h->fd, h->in,
532 MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
611 MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
533 if (h->resp_len == -1) {
612 if (h->in_len == -1) {
534 generr(h, "recvfrom: %s", strerror(errno));
535 return -1;
536 }
537 if (is_valid_response(h, h->srv, &from)) {
613 generr(h, "recvfrom: %s", strerror(errno));
614 return -1;
615 }
616 if (is_valid_response(h, h->srv, &from)) {
538 h->resp_len = h->response[POS_LENGTH] << 8 |
539 h->response[POS_LENGTH+1];
540 h->resp_pos = POS_ATTRS;
541 return h->response[POS_CODE];
617 h->in_len = h->in[POS_LENGTH] << 8 |
618 h->in[POS_LENGTH+1];
619 h->in_pos = POS_ATTRS;
620 return h->in[POS_CODE];
542 }
543 }
544
545 if (h->try == h->total_tries) {
546 generr(h, "No valid RADIUS responses received");
547 return -1;
548 }
549
550 /*
551 * Scan round-robin to the next server that has some
552 * tries left. There is guaranteed to be one, or we
553 * would have exited this loop by now.
554 */
555 while (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries)
556 if (++h->srv >= h->num_servers)
557 h->srv = 0;
558
621 }
622 }
623
624 if (h->try == h->total_tries) {
625 generr(h, "No valid RADIUS responses received");
626 return -1;
627 }
628
629 /*
630 * Scan round-robin to the next server that has some
631 * tries left. There is guaranteed to be one, or we
632 * would have exited this loop by now.
633 */
634 while (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries)
635 if (++h->srv >= h->num_servers)
636 h->srv = 0;
637
559 if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
560 /* Insert the request authenticator into the request */
561 insert_request_authenticator(h, h->srv);
562 else
638 if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
563 /* Insert the scrambled password into the request */
564 if (h->pass_pos != 0)
565 insert_scrambled_password(h, h->srv);
639 /* Insert the scrambled password into the request */
640 if (h->pass_pos != 0)
641 insert_scrambled_password(h, h->srv);
642 }
643 insert_message_authenticator(h, 0);
644 if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
645 /* Insert the request authenticator into the request */
646 insert_request_authenticator(h, h->srv);
647 }
566
648
567 insert_message_authenticator(h, h->srv);
568
569 /* Send the request */
649 /* Send the request */
570 n = sendto(h->fd, h->request, h->req_len, 0,
650 n = sendto(h->fd, h->out, h->out_len, 0,
571 (const struct sockaddr *)&h->servers[h->srv].addr,
572 sizeof h->servers[h->srv].addr);
651 (const struct sockaddr *)&h->servers[h->srv].addr,
652 sizeof h->servers[h->srv].addr);
573 if (n != h->req_len) {
653 if (n != h->out_len) {
574 if (n == -1)
575 generr(h, "sendto: %s", strerror(errno));
576 else
577 generr(h, "sendto: short write");
578 return -1;
579 }
580
581 h->try++;
582 h->servers[h->srv].num_tries++;
583 tv->tv_sec = h->servers[h->srv].timeout;
584 tv->tv_usec = 0;
585 *fd = h->fd;
586
587 return 0;
588}
589
590int
654 if (n == -1)
655 generr(h, "sendto: %s", strerror(errno));
656 else
657 generr(h, "sendto: short write");
658 return -1;
659 }
660
661 h->try++;
662 h->servers[h->srv].num_tries++;
663 tv->tv_sec = h->servers[h->srv].timeout;
664 tv->tv_usec = 0;
665 *fd = h->fd;
666
667 return 0;
668}
669
670int
671rad_receive_request(struct rad_handle *h)
672{
673 struct sockaddr_in from;
674 socklen_t fromlen;
675 int n;
676
677 if (h->type != RADIUS_SERVER) {
678 generr(h, "denied function call");
679 return (-1);
680 }
681 h->srv = -1;
682 fromlen = sizeof(from);
683 h->in_len = recvfrom(h->fd, h->in,
684 MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
685 if (h->in_len == -1) {
686 generr(h, "recvfrom: %s", strerror(errno));
687 return (-1);
688 }
689 for (n = 0; n < h->num_servers; n++) {
690 if (h->servers[n].addr.sin_addr.s_addr == from.sin_addr.s_addr) {
691 h->servers[n].addr.sin_port = from.sin_port;
692 h->srv = n;
693 break;
694 }
695 }
696 if (h->srv == -1)
697 return (-2);
698 if (is_valid_request(h)) {
699 h->in_len = h->in[POS_LENGTH] << 8 |
700 h->in[POS_LENGTH+1];
701 h->in_pos = POS_ATTRS;
702 return (h->in[POS_CODE]);
703 }
704 return (-3);
705}
706
707int
708rad_send_response(struct rad_handle *h)
709{
710 int n;
711
712 if (h->type != RADIUS_SERVER) {
713 generr(h, "denied function call");
714 return (-1);
715 }
716 /* Fill in the length field in the message */
717 h->out[POS_LENGTH] = h->out_len >> 8;
718 h->out[POS_LENGTH+1] = h->out_len;
719
720 insert_message_authenticator(h,
721 (h->in[POS_CODE] == RAD_ACCESS_REQUEST) ? 1 : 0);
722 insert_request_authenticator(h, 1);
723
724 /* Send the request */
725 n = sendto(h->fd, h->out, h->out_len, 0,
726 (const struct sockaddr *)&h->servers[h->srv].addr,
727 sizeof h->servers[h->srv].addr);
728 if (n != h->out_len) {
729 if (n == -1)
730 generr(h, "sendto: %s", strerror(errno));
731 else
732 generr(h, "sendto: short write");
733 return -1;
734 }
735
736 return 0;
737}
738
739int
591rad_create_request(struct rad_handle *h, int code)
592{
593 int i;
594
740rad_create_request(struct rad_handle *h, int code)
741{
742 int i;
743
595 h->request[POS_CODE] = code;
596 h->request[POS_IDENT] = ++h->ident;
597 /* Create a random authenticator */
598 for (i = 0; i < LEN_AUTH; i += 2) {
599 long r;
600 r = random();
601 h->request[POS_AUTH+i] = (u_char)r;
602 h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
744 if (h->type == RADIUS_SERVER) {
745 generr(h, "denied function call");
746 return (-1);
603 }
747 }
604 h->req_len = POS_ATTRS;
748 h->out[POS_CODE] = code;
749 h->out[POS_IDENT] = ++h->ident;
750 if (code == RAD_ACCESS_REQUEST) {
751 /* Create a random authenticator */
752 for (i = 0; i < LEN_AUTH; i += 2) {
753 long r;
754 r = random();
755 h->out[POS_AUTH+i] = (u_char)r;
756 h->out[POS_AUTH+i+1] = (u_char)(r >> 8);
757 }
758 } else
759 memset(&h->out[POS_AUTH], 0, LEN_AUTH);
760 h->out_len = POS_ATTRS;
605 clear_password(h);
761 clear_password(h);
606 h->request_created = 1;
762 h->authentic_pos = 0;
763 h->out_created = 1;
607 return 0;
608}
609
764 return 0;
765}
766
767int
768rad_create_response(struct rad_handle *h, int code)
769{
770
771 if (h->type != RADIUS_SERVER) {
772 generr(h, "denied function call");
773 return (-1);
774 }
775 h->out[POS_CODE] = code;
776 h->out[POS_IDENT] = h->in[POS_IDENT];
777 memset(&h->out[POS_AUTH], 0, LEN_AUTH);
778 h->out_len = POS_ATTRS;
779 clear_password(h);
780 h->authentic_pos = 0;
781 h->out_created = 1;
782 return 0;
783}
784
610struct in_addr
611rad_cvt_addr(const void *data)
612{
613 struct in_addr value;
614
615 memcpy(&value.s_addr, data, sizeof value.s_addr);
616 return value;
617}

--- 24 unchanged lines hidden (view full) ---

642 * Returns the attribute type. If none are left, returns 0. On failure,
643 * returns -1.
644 */
645int
646rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
647{
648 int type;
649
785struct in_addr
786rad_cvt_addr(const void *data)
787{
788 struct in_addr value;
789
790 memcpy(&value.s_addr, data, sizeof value.s_addr);
791 return value;
792}

--- 24 unchanged lines hidden (view full) ---

817 * Returns the attribute type. If none are left, returns 0. On failure,
818 * returns -1.
819 */
820int
821rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
822{
823 int type;
824
650 if (h->resp_pos >= h->resp_len)
825 if (h->in_pos >= h->in_len)
651 return 0;
826 return 0;
652 if (h->resp_pos + 2 > h->resp_len) {
827 if (h->in_pos + 2 > h->in_len) {
653 generr(h, "Malformed attribute in response");
654 return -1;
655 }
828 generr(h, "Malformed attribute in response");
829 return -1;
830 }
656 type = h->response[h->resp_pos++];
657 *len = h->response[h->resp_pos++] - 2;
658 if (h->resp_pos + (int)*len > h->resp_len) {
831 type = h->in[h->in_pos++];
832 *len = h->in[h->in_pos++] - 2;
833 if (h->in_pos + (int)*len > h->in_len) {
659 generr(h, "Malformed attribute in response");
660 return -1;
661 }
834 generr(h, "Malformed attribute in response");
835 return -1;
836 }
662 *value = &h->response[h->resp_pos];
663 h->resp_pos += *len;
837 *value = &h->in[h->in_pos];
838 h->in_pos += *len;
664 return type;
665}
666
667/*
668 * Returns -1 on error, 0 to indicate no event and >0 for success
669 */
670int
671rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
672{
673 int srv;
674
839 return type;
840}
841
842/*
843 * Returns -1 on error, 0 to indicate no event and >0 for success
844 */
845int
846rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
847{
848 int srv;
849
850 if (h->type == RADIUS_SERVER) {
851 generr(h, "denied function call");
852 return (-1);
853 }
675 /* Make sure we have a socket to use */
676 if (h->fd == -1) {
677 struct sockaddr_in sin;
678
679 if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
680 generr(h, "Cannot create socket: %s", strerror(errno));
681 return -1;
682 }

--- 6 unchanged lines hidden (view full) ---

689 sizeof sin) == -1) {
690 generr(h, "bind: %s", strerror(errno));
691 close(h->fd);
692 h->fd = -1;
693 return -1;
694 }
695 }
696
854 /* Make sure we have a socket to use */
855 if (h->fd == -1) {
856 struct sockaddr_in sin;
857
858 if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
859 generr(h, "Cannot create socket: %s", strerror(errno));
860 return -1;
861 }

--- 6 unchanged lines hidden (view full) ---

868 sizeof sin) == -1) {
869 generr(h, "bind: %s", strerror(errno));
870 close(h->fd);
871 h->fd = -1;
872 return -1;
873 }
874 }
875
697 if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
876 if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
698 /* Make sure no password given */
699 if (h->pass_pos || h->chap_pass) {
700 generr(h, "User or Chap Password"
701 " in accounting request");
702 return -1;
703 }
704 } else {
705 if (h->eap_msg == 0) {

--- 7 unchanged lines hidden (view full) ---

713 generr(h, "Both User and Chap Password"
714 " attributes given");
715 return -1;
716 }
717 }
718 }
719
720 /* Fill in the length field in the message */
877 /* Make sure no password given */
878 if (h->pass_pos || h->chap_pass) {
879 generr(h, "User or Chap Password"
880 " in accounting request");
881 return -1;
882 }
883 } else {
884 if (h->eap_msg == 0) {

--- 7 unchanged lines hidden (view full) ---

892 generr(h, "Both User and Chap Password"
893 " attributes given");
894 return -1;
895 }
896 }
897 }
898
899 /* Fill in the length field in the message */
721 h->request[POS_LENGTH] = h->req_len >> 8;
722 h->request[POS_LENGTH+1] = h->req_len;
900 h->out[POS_LENGTH] = h->out_len >> 8;
901 h->out[POS_LENGTH+1] = h->out_len;
723
724 /*
725 * Count the total number of tries we will make, and zero the
726 * counter for each server.
727 */
728 h->total_tries = 0;
729 for (srv = 0; srv < h->num_servers; srv++) {
730 h->total_tries += h->servers[srv].max_tries;

--- 27 unchanged lines hidden (view full) ---

758 h->ident = random();
759 h->errmsg[0] = '\0';
760 memset(h->pass, 0, sizeof h->pass);
761 h->pass_len = 0;
762 h->pass_pos = 0;
763 h->chap_pass = 0;
764 h->authentic_pos = 0;
765 h->type = RADIUS_AUTH;
902
903 /*
904 * Count the total number of tries we will make, and zero the
905 * counter for each server.
906 */
907 h->total_tries = 0;
908 for (srv = 0; srv < h->num_servers; srv++) {
909 h->total_tries += h->servers[srv].max_tries;

--- 27 unchanged lines hidden (view full) ---

937 h->ident = random();
938 h->errmsg[0] = '\0';
939 memset(h->pass, 0, sizeof h->pass);
940 h->pass_len = 0;
941 h->pass_pos = 0;
942 h->chap_pass = 0;
943 h->authentic_pos = 0;
944 h->type = RADIUS_AUTH;
766 h->request_created = 0;
945 h->out_created = 0;
767 h->eap_msg = 0;
768 }
769 return h;
770}
771
772struct rad_handle *
773rad_acct_open(void)
774{
775 struct rad_handle *h;
776
777 h = rad_open();
778 if (h != NULL)
779 h->type = RADIUS_ACCT;
780 return h;
781}
782
783struct rad_handle *
946 h->eap_msg = 0;
947 }
948 return h;
949}
950
951struct rad_handle *
952rad_acct_open(void)
953{
954 struct rad_handle *h;
955
956 h = rad_open();
957 if (h != NULL)
958 h->type = RADIUS_ACCT;
959 return h;
960}
961
962struct rad_handle *
963rad_server_open(int fd)
964{
965 struct rad_handle *h;
966
967 h = rad_open();
968 if (h != NULL) {
969 h->type = RADIUS_SERVER;
970 h->fd = fd;
971 }
972 return h;
973}
974
975struct rad_handle *
784rad_open(void)
785{
786 return rad_auth_open();
787}
788
789int
790rad_put_addr(struct rad_handle *h, int type, struct in_addr addr)
791{
792 return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
793}
794
795int
796rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
797{
798 int result;
799
976rad_open(void)
977{
978 return rad_auth_open();
979}
980
981int
982rad_put_addr(struct rad_handle *h, int type, struct in_addr addr)
983{
984 return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
985}
986
987int
988rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
989{
990 int result;
991
800 if (!h->request_created) {
992 if (!h->out_created) {
801 generr(h, "Please call rad_create_request()"
802 " before putting attributes");
803 return -1;
804 }
805
993 generr(h, "Please call rad_create_request()"
994 " before putting attributes");
995 return -1;
996 }
997
806 if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
998 if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
807 if (type == RAD_EAP_MESSAGE) {
808 generr(h, "EAP-Message attribute is not valid"
809 " in accounting requests");
810 return -1;
811 }
812 }
813
814 /*

--- 38 unchanged lines hidden (view full) ---

853}
854
855int
856rad_put_message_authentic(struct rad_handle *h)
857{
858#ifdef WITH_SSL
859 u_char md_zero[MD5_DIGEST_LENGTH];
860
999 if (type == RAD_EAP_MESSAGE) {
1000 generr(h, "EAP-Message attribute is not valid"
1001 " in accounting requests");
1002 return -1;
1003 }
1004 }
1005
1006 /*

--- 38 unchanged lines hidden (view full) ---

1045}
1046
1047int
1048rad_put_message_authentic(struct rad_handle *h)
1049{
1050#ifdef WITH_SSL
1051 u_char md_zero[MD5_DIGEST_LENGTH];
1052
861 if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
1053 if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
862 generr(h, "Message-Authenticator is not valid"
863 " in accounting requests");
864 return -1;
865 }
866
867 if (h->authentic_pos == 0) {
1054 generr(h, "Message-Authenticator is not valid"
1055 " in accounting requests");
1056 return -1;
1057 }
1058
1059 if (h->authentic_pos == 0) {
868 h->authentic_pos = h->req_len;
1060 h->authentic_pos = h->out_len;
869 memset(md_zero, 0, sizeof(md_zero));
870 return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
871 sizeof(md_zero)));
872 }
873 return 0;
874#else
875 generr(h, "Message Authenticator not supported,"
876 " please recompile libradius with SSL support");

--- 159 unchanged lines hidden (view full) ---

1036
1037int
1038rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
1039 const void *value, size_t len)
1040{
1041 struct vendor_attribute *attr;
1042 int res;
1043
1061 memset(md_zero, 0, sizeof(md_zero));
1062 return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
1063 sizeof(md_zero)));
1064 }
1065 return 0;
1066#else
1067 generr(h, "Message Authenticator not supported,"
1068 " please recompile libradius with SSL support");

--- 159 unchanged lines hidden (view full) ---

1228
1229int
1230rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
1231 const void *value, size_t len)
1232{
1233 struct vendor_attribute *attr;
1234 int res;
1235
1044 if (!h->request_created) {
1236 if (!h->out_created) {
1045 generr(h, "Please call rad_create_request()"
1046 " before putting attributes");
1047 return -1;
1048 }
1049
1050 if ((attr = malloc(len + 6)) == NULL) {
1051 generr(h, "malloc failure (%zu bytes)", len + 6);
1052 return -1;

--- 30 unchanged lines hidden (view full) ---

1083 return (rad_put_vendor_attr(h, vendor, type, str, strlen(str)));
1084}
1085
1086ssize_t
1087rad_request_authenticator(struct rad_handle *h, char *buf, size_t len)
1088{
1089 if (len < LEN_AUTH)
1090 return (-1);
1237 generr(h, "Please call rad_create_request()"
1238 " before putting attributes");
1239 return -1;
1240 }
1241
1242 if ((attr = malloc(len + 6)) == NULL) {
1243 generr(h, "malloc failure (%zu bytes)", len + 6);
1244 return -1;

--- 30 unchanged lines hidden (view full) ---

1275 return (rad_put_vendor_attr(h, vendor, type, str, strlen(str)));
1276}
1277
1278ssize_t
1279rad_request_authenticator(struct rad_handle *h, char *buf, size_t len)
1280{
1281 if (len < LEN_AUTH)
1282 return (-1);
1091 memcpy(buf, h->request + POS_AUTH, LEN_AUTH);
1283 memcpy(buf, h->out + POS_AUTH, LEN_AUTH);
1092 if (len > LEN_AUTH)
1093 buf[LEN_AUTH] = '\0';
1094 return (LEN_AUTH);
1095}
1096
1097u_char *
1098rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen)
1099{

--- 134 unchanged lines hidden ---
1284 if (len > LEN_AUTH)
1285 buf[LEN_AUTH] = '\0';
1286 return (LEN_AUTH);
1287}
1288
1289u_char *
1290rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen)
1291{

--- 134 unchanged lines hidden ---