sendserver.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*
  2. * $Id: sendserver.c,v 1.30 2010/06/15 09:22:52 aland Exp $
  3. *
  4. * Copyright (C) 1995,1996,1997 Lars Fenneberg
  5. *
  6. * Copyright 1992 Livingston Enterprises, Inc.
  7. *
  8. * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
  9. * and Merit Network, Inc. All Rights Reserved
  10. *
  11. * See the file COPYRIGHT for the respective terms and conditions.
  12. * If the file is missing contact me at lf@elemental.net
  13. * and I'll send you a copy.
  14. *
  15. */
  16. //#include <poll.h>
  17. #include <radius_config.h>
  18. #include <includes.h>
  19. #include <freeradius-client.h>
  20. #include <pathnames.h>
  21. #include "freeradius-client.h"
  22. #include "util.h"
  23. #include "radius_user.h"
  24. #include "parameters.h"
  25. #include "lwip/sockets.h"
  26. #define SA(p) ((struct sockaddr *)(p))
  27. static void rc_random_vector (unsigned char *);
  28. static int rc_check_reply (AUTH_HDR *, int, char const *, unsigned char const *, unsigned char);
  29. /** Packs an attribute value pair list into a buffer
  30. *
  31. * @param vp a pointer to a #VALUE_PAIR.
  32. * @param secret the secret used by the server.
  33. * @param auth a pointer to #AUTH_HDR.
  34. * @return The number of octets packed.
  35. */
  36. static int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth)
  37. {
  38. int length, i, pc, padded_length;
  39. int total_length = 0;
  40. size_t secretlen;
  41. uint32_t lvalue, vendor;
  42. unsigned char passbuf[MAX(AUTH_PASS_LEN, CHAP_VALUE_LENGTH)];
  43. unsigned char md5buf[256];
  44. unsigned char *buf, *vector, *vsa_length_ptr;
  45. buf = auth->data;
  46. while (vp != NULL)
  47. {
  48. vsa_length_ptr = NULL;
  49. if (VENDOR(vp->attribute) != 0) {
  50. *buf++ = PW_VENDOR_SPECIFIC;
  51. vsa_length_ptr = buf;
  52. *buf++ = 6;
  53. vendor = htonl(VENDOR(vp->attribute));
  54. memcpy(buf, &vendor, sizeof(uint32_t));
  55. buf += 4;
  56. total_length += 6;
  57. }
  58. *buf++ = (vp->attribute & 0xff);
  59. switch (vp->attribute)
  60. {
  61. case PW_USER_PASSWORD:
  62. /* Encrypt the password */
  63. /* Chop off password at AUTH_PASS_LEN */
  64. length = vp->lvalue;
  65. if (length > AUTH_PASS_LEN)
  66. length = AUTH_PASS_LEN;
  67. /* Calculate the padded length */
  68. padded_length = (length+(AUTH_VECTOR_LEN-1)) & ~(AUTH_VECTOR_LEN-1);
  69. /* Record the attribute length */
  70. *buf++ = padded_length + 2;
  71. if (vsa_length_ptr != NULL) *vsa_length_ptr += padded_length + 2;
  72. /* Pad the password with zeros */
  73. memset ((char *) passbuf, '\0', AUTH_PASS_LEN);
  74. memcpy ((char *) passbuf, vp->strvalue, (size_t) length);
  75. secretlen = strlen (secret);
  76. vector = (unsigned char *)auth->vector;
  77. for(i = 0; i < padded_length; i += AUTH_VECTOR_LEN)
  78. {
  79. /* Calculate the MD5 digest*/
  80. strcpy ((char *) md5buf, secret);
  81. memcpy ((char *) md5buf + secretlen, vector,
  82. AUTH_VECTOR_LEN);
  83. rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN);
  84. /* Remeber the start of the digest */
  85. vector = buf;
  86. /* Xor the password into the MD5 digest */
  87. for (pc = i; pc < (i + AUTH_VECTOR_LEN); pc++)
  88. {
  89. *buf++ ^= passbuf[pc];
  90. }
  91. }
  92. total_length += padded_length + 2;
  93. break;
  94. default:
  95. switch (vp->type)
  96. {
  97. case PW_TYPE_STRING:
  98. length = vp->lvalue;
  99. *buf++ = length + 2;
  100. if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
  101. memcpy (buf, vp->strvalue, (size_t) length);
  102. buf += length;
  103. total_length += length + 2;
  104. break;
  105. case PW_TYPE_IPV6ADDR:
  106. length = 16;
  107. *buf++ = length + 2;
  108. if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
  109. memcpy (buf, vp->strvalue, (size_t) length);
  110. buf += length;
  111. total_length += length + 2;
  112. break;
  113. case PW_TYPE_IPV6PREFIX:
  114. length = vp->lvalue;
  115. *buf++ = length + 2;
  116. if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
  117. memcpy (buf, vp->strvalue, (size_t) length);
  118. buf += length;
  119. total_length += length + 2;
  120. break;
  121. case PW_TYPE_INTEGER:
  122. case PW_TYPE_IPADDR:
  123. case PW_TYPE_DATE:
  124. *buf++ = sizeof (uint32_t) + 2;
  125. if (vsa_length_ptr != NULL) *vsa_length_ptr += sizeof(uint32_t) + 2;
  126. lvalue = htonl (vp->lvalue);
  127. memcpy (buf, (char *) &lvalue, sizeof (uint32_t));
  128. buf += sizeof (uint32_t);
  129. total_length += sizeof (uint32_t) + 2;
  130. break;
  131. default:
  132. break;
  133. }
  134. break;
  135. }
  136. vp = vp->next;
  137. }
  138. return total_length;
  139. }
  140. /** Appends a string to the provided buffer
  141. *
  142. * @param dest the destination buffer.
  143. * @param max_size the maximum size available in the destination buffer.
  144. * @param pos the current position in the dest buffer; initially must be zero.
  145. * @param src the source buffer to append.
  146. */
  147. static void strappend(char *dest, unsigned max_size, int *pos, const char *src)
  148. {
  149. unsigned len = strlen(src) + 1;
  150. if (*pos == -1)
  151. return;
  152. if (len + *pos > max_size) {
  153. *pos = -1;
  154. return;
  155. }
  156. memcpy(&dest[*pos], src, len);
  157. *pos += len-1;
  158. return;
  159. }
  160. /** Sends a request to a RADIUS server and waits for the reply
  161. *
  162. * @param rh a handle to parsed configuration
  163. * @param data a pointer to a #SEND_DATA structure
  164. * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of
  165. * any %PW_REPLY_MESSAGE received.
  166. * @param flags must be %AUTH or %ACCT
  167. * @return %OK_RC (0) on success, %TIMEOUT_RC on timeout %REJECT_RC on acess reject, or negative
  168. * on failure as return value.
  169. */
  170. #define RECV_BUF_LEN 300
  171. static char recv_buffer[RECV_BUF_LEN];
  172. int rc_send_server (rc_handle *rh, SEND_DATA *data, char *msg, unsigned flags)
  173. {
  174. struct sockaddr_in sa,ra;
  175. int socket;
  176. fdsets sets;
  177. AUTH_HDR* auth;
  178. AUTH_HDR* recv_auth;
  179. unsigned char vector[AUTH_VECTOR_LEN];
  180. char secret[MAX_SECRET_LENGTH + 1];
  181. int total_length;
  182. int sendLen, recvLen;
  183. int length;
  184. int pos;
  185. uint8_t* attr;
  186. int result = 0;
  187. VALUE_PAIR* vp;
  188. char rcNetParams[20];
  189. uint32_t port;
  190. uint8_t tmpLen;
  191. initFdsets(&sets);
  192. memset(secret, 0, MAX_SECRET_LENGTH + 1);
  193. GetRDSPasswordkStr(secret, &tmpLen);
  194. /*
  195. if(data->secret != NULL) {
  196. //strlcpy(secret, data->secret, MAX_SECRET_LENGTH);
  197. strlcpy(secret, "R04ekR4MP2", MAX_SECRET_LENGTH);
  198. }
  199. */
  200. // Устанавливаем сетевые параметры
  201. memset(rcNetParams, 0, 20);
  202. GetRDSIpStr(rcNetParams, &tmpLen);
  203. // IP radius server
  204. memset(&ra, 0, sizeof(struct sockaddr_in));
  205. ra.sin_family = AF_INET;
  206. ra.sin_addr.s_addr = inet_addr(rcNetParams);
  207. // port
  208. memset(rcNetParams, 0, 20);
  209. GetRDSPortStr(rcNetParams, &tmpLen);
  210. port = atoi(rcNetParams);
  211. ra.sin_port = htons(port);
  212. socket = socket(PF_INET, SOCK_DGRAM, 0);
  213. if ( socket < 0 )
  214. {
  215. //printf("socket call failed");
  216. return -1;
  217. }
  218. // Build a request (PW_ACCESS_REQUEST)
  219. auth = (AUTH_HDR *) msg;
  220. auth->code = data->code;
  221. auth->id = data->seq_nbr;
  222. rc_random_vector(vector);
  223. memcpy((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
  224. total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN;
  225. auth->length = htons ((unsigned short) total_length);
  226. // Bind socket
  227. memset(rcNetParams, 0, 20);
  228. GetIpStr(rcNetParams, &tmpLen);
  229. memset(&sa, 0, sizeof(struct sockaddr_in));
  230. sa.sin_family = AF_INET;
  231. sa.sin_addr.s_addr = inet_addr(rcNetParams);
  232. sa.sin_port = htons(port);
  233. if (bind(socket, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1)
  234. {
  235. //printf("Bind to Port Number %d ,IP address %s failed\n", DEVICE_PORT_NUM, DEVICE_IP_ADDR);
  236. close(socket);
  237. return -1;
  238. }
  239. sendLen = sendto(socket, (char*)auth, total_length, 0, (struct sockaddr*)&ra, sizeof(ra));
  240. if(sendLen < 0)
  241. {
  242. //printf("send failed\n");
  243. close(socket);
  244. return NET_ERR_RC;
  245. }
  246. // Подготовка буфера для приема
  247. memset(recv_buffer, 0, RECV_BUF_LEN);
  248. // Получение ответа, select
  249. if (!recvSelect(&sets, &socket, 2000)) {
  250. //printf("SOCK recv timeout!\r\n");
  251. close(socket);
  252. return NET_ERR_RC;
  253. }
  254. // Данные можно принимать
  255. socklen_t sl = sizeof(sa);
  256. recvLen = recvfrom(socket, recv_buffer, RECV_BUF_LEN, 0, (struct sockaddr*)&ra, &sl);
  257. recv_auth = (AUTH_HDR*)recv_buffer;
  258. // Проверки размера входящего сообщения
  259. if (recvLen < AUTH_HDR_LEN || recvLen < ntohs(recv_auth->length)) {
  260. //printf("radius_server: reply is too short\r\n");
  261. close(socket);
  262. return NET_ERR_RC;
  263. }
  264. if (recvLen > ntohs(recv_auth->length))
  265. {
  266. recvLen = ntohs(recv_auth->length);
  267. }
  268. // Verify that it's a valid RADIUS packet before doing ANYTHING with it.
  269. attr = recv_buffer + AUTH_HDR_LEN;
  270. while (attr < (recv_buffer + recvLen)) {
  271. if (attr[0] == 0) {
  272. //printf("radius_server: attribute zero is invalid\r\n");
  273. close(socket);
  274. return NET_ERR_RC;
  275. }
  276. if (attr[1] < 2) {
  277. //printf("radius_server: attribute length is too small\r\n");
  278. close(socket);
  279. return NET_ERR_RC;
  280. }
  281. if ((attr + attr[1]) > (recv_buffer + recvLen)) {
  282. //printf("radius_server: attribute overflows the packet\r\n");
  283. close(socket);
  284. return NET_ERR_RC;
  285. }
  286. attr += attr[1];
  287. }
  288. result = rc_check_reply(recv_auth, RECV_BUF_LEN, secret, vector, data->seq_nbr);
  289. length = ntohs(recv_auth->length) - AUTH_HDR_LEN;
  290. if (length > 0) {
  291. data->receive_pairs = rc_avpair_gen(rh, NULL, recv_auth->data, length, 0);
  292. } else {
  293. data->receive_pairs = NULL;
  294. }
  295. if (result != OK_RC) {
  296. return result;
  297. }
  298. if (msg) {
  299. *msg = '\0';
  300. pos = 0;
  301. vp = data->receive_pairs;
  302. while (vp)
  303. {
  304. if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE, 0)))
  305. {
  306. strappend(msg, PW_MAX_MSG_SIZE, &pos, vp->strvalue);
  307. strappend(msg, PW_MAX_MSG_SIZE, &pos, "\n");
  308. vp = vp->next;
  309. }
  310. }
  311. }
  312. if ((recv_auth->code == PW_ACCESS_ACCEPT) ||
  313. (recv_auth->code == PW_PASSWORD_ACK) ||
  314. (recv_auth->code == PW_ACCOUNTING_RESPONSE))
  315. {
  316. result = RC_GetAccessRights(recv_buffer);
  317. }
  318. else if ((recv_auth->code == PW_ACCESS_REJECT) ||
  319. (recv_auth->code == PW_PASSWORD_REJECT))
  320. {
  321. result = REJECT_RC;
  322. }
  323. else
  324. {
  325. rc_log(LOG_ERR, "rc_send_server: received RADIUS server response neither ACCEPT nor REJECT, invalid");
  326. result = BADRESP_RC;
  327. }
  328. //printf("\r\nRadius server end communication\r\n");
  329. close(socket);
  330. return result;
  331. }
  332. /** Verify items in returned packet
  333. *
  334. * @param auth a pointer to #AUTH_HDR.
  335. * @param bufferlen the available buffer length.
  336. * @param secret the secret used by the server.
  337. * @param vector a random vector of %AUTH_VECTOR_LEN.
  338. * @param seq_nbr a unique sequence number.
  339. * @return %OK_RC upon success, %BADRESP_RC if anything looks funny.
  340. */
  341. static int rc_check_reply (AUTH_HDR *auth, int bufferlen, char const *secret, unsigned char const *vector, uint8_t seq_nbr)
  342. {
  343. int secretlen;
  344. int totallen;
  345. unsigned char calc_digest[AUTH_VECTOR_LEN];
  346. unsigned char reply_digest[AUTH_VECTOR_LEN];
  347. #ifdef DIGEST_DEBUG
  348. uint8_t *ptr;
  349. #endif
  350. totallen = ntohs (auth->length);
  351. secretlen = (int)strlen (secret);
  352. /* Do sanity checks on packet length */
  353. if ((totallen < 20) || (totallen > 4096))
  354. {
  355. rc_log(LOG_ERR, "rc_check_reply: received RADIUS server response with invalid length");
  356. return BADRESP_RC;
  357. }
  358. /* Verify buffer space, should never trigger with current buffer size and check above */
  359. if ((totallen + secretlen) > bufferlen)
  360. {
  361. rc_log(LOG_ERR, "rc_check_reply: not enough buffer space to verify RADIUS server response");
  362. return BADRESP_RC;
  363. }
  364. /* Verify that id (seq. number) matches what we sent */
  365. if (auth->id != seq_nbr)
  366. {
  367. rc_log(LOG_ERR, "rc_check_reply: received non-matching id in RADIUS server response");
  368. return BADRESP_RC;
  369. }
  370. /* Verify the reply digest */
  371. memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN);
  372. memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
  373. memcpy ((char *) auth + totallen, secret, secretlen);
  374. #ifdef DIGEST_DEBUG
  375. rc_log(LOG_ERR, "Calculating digest on:");
  376. for (ptr = (u_char *)auth; ptr < ((u_char *)auth) + totallen + secretlen; ptr += 32) {
  377. char buf[65];
  378. int i;
  379. buf[0] = '\0';
  380. for (i = 0; i < 32; i++) {
  381. if (ptr + i >= ((u_char *)auth) + totallen + secretlen)
  382. break;
  383. sprintf(buf + i * 2, "%.2X", ptr[i]);
  384. }
  385. rc_log(LOG_ERR, " %s", buf);
  386. }
  387. #endif
  388. rc_md5_calc (calc_digest, (unsigned char *) auth, totallen + secretlen);
  389. #ifdef DIGEST_DEBUG
  390. rc_log(LOG_ERR, "Calculated digest is:");
  391. for (ptr = (u_char *)calc_digest; ptr < ((u_char *)calc_digest) + 16; ptr += 32) {
  392. char buf[65];
  393. int i;
  394. buf[0] = '\0';
  395. for (i = 0; i < 32; i++) {
  396. if (ptr + i >= ((u_char *)calc_digest) + 16)
  397. break;
  398. sprintf(buf + i * 2, "%.2X", ptr[i]);
  399. }
  400. rc_log(LOG_ERR, " %s", buf);
  401. }
  402. rc_log(LOG_ERR, "Reply digest is:");
  403. for (ptr = (u_char *)reply_digest; ptr < ((u_char *)reply_digest) + 16; ptr += 32) {
  404. char buf[65];
  405. int i;
  406. buf[0] = '\0';
  407. for (i = 0; i < 32; i++) {
  408. if (ptr + i >= ((u_char *)reply_digest) + 16)
  409. break;
  410. sprintf(buf + i * 2, "%.2X", ptr[i]);
  411. }
  412. rc_log(LOG_ERR, " %s", buf);
  413. }
  414. #endif
  415. if (memcmp ((char *) reply_digest, (char *) calc_digest,
  416. AUTH_VECTOR_LEN) != 0)
  417. {
  418. rc_log(LOG_ERR, "rc_check_reply: received invalid reply digest from RADIUS server");
  419. return BADRESP_RC;
  420. }
  421. return OK_RC;
  422. }
  423. /** Generates a random vector of AUTH_VECTOR_LEN octets
  424. *
  425. * @param vector a buffer with at least %AUTH_VECTOR_LEN bytes.
  426. */
  427. static void rc_random_vector (unsigned char *vector)
  428. {
  429. int randno;
  430. int i;
  431. #if defined(HAVE_GETENTROPY)
  432. if (getentropy(vector, AUTH_VECTOR_LEN) >= 0) {
  433. return;
  434. } /* else fall through */
  435. #elif defined(HAVE_DEV_URANDOM)
  436. int fd;
  437. /* well, I added this to increase the security for user passwords.
  438. we use /dev/urandom here, as /dev/random might block and we don't
  439. need that much randomness. BTW, great idea, Ted! -lf, 03/18/95 */
  440. if ((fd = open(_PATH_DEV_URANDOM, O_RDONLY)) >= 0)
  441. {
  442. unsigned char *pos;
  443. int readcount;
  444. i = AUTH_VECTOR_LEN;
  445. pos = vector;
  446. while (i > 0)
  447. {
  448. readcount = read(fd, (char *)pos, i);
  449. if (readcount >= 0) {
  450. pos += readcount;
  451. i -= readcount;
  452. } else {
  453. if (errno != EINTR && errno != EAGAIN)
  454. goto fallback;
  455. }
  456. }
  457. close(fd);
  458. return;
  459. } /* else fall through */
  460. #endif
  461. fallback:
  462. for (i = 0; i < AUTH_VECTOR_LEN;)
  463. {
  464. randno = random ();
  465. memcpy ((char *) vector, (char *) &randno, sizeof (int));
  466. vector += sizeof (int);
  467. i += sizeof (int);
  468. }
  469. return;
  470. }