buildreq.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * $Id: buildreq.c,v 1.1 2004/11/14 07:26:26 paulus Exp $
  3. *
  4. * Copyright (C) 1995,1997 Lars Fenneberg
  5. *
  6. * See the file COPYRIGHT for the respective terms and conditions.
  7. * If the file is missing contact me at lf@elemental.net
  8. * and I'll send you a copy.
  9. *
  10. */
  11. #include <includes.h>
  12. #include <radiusclient.h>
  13. unsigned char rc_get_seqnbr(void);
  14. /*
  15. * Function: rc_get_nas_id
  16. *
  17. * Purpose: fills in NAS-Identifier or NAS-IP-Address in request
  18. *
  19. */
  20. int rc_get_nas_id(VALUE_PAIR **sendpairs)
  21. {
  22. UINT4 client_id;
  23. char *nasid;
  24. nasid = rc_conf_str("nas_identifier");
  25. if (strlen(nasid)) {
  26. /*
  27. * Fill in NAS-Identifier
  28. */
  29. if (rc_avpair_add(sendpairs, PW_NAS_IDENTIFIER, nasid, 0,
  30. VENDOR_NONE) == NULL)
  31. return (ERROR_RC);
  32. return (OK_RC);
  33. } else {
  34. /*
  35. * Fill in NAS-IP-Address
  36. */
  37. if ((client_id = rc_own_ipaddress()) == 0)
  38. return (ERROR_RC);
  39. if (rc_avpair_add(sendpairs, PW_NAS_IP_ADDRESS, &client_id,
  40. 0, VENDOR_NONE) == NULL)
  41. return (ERROR_RC);
  42. }
  43. return (OK_RC);
  44. }
  45. /*
  46. * Function: rc_buildreq
  47. *
  48. * Purpose: builds a skeleton RADIUS request using information from the
  49. * config file.
  50. *
  51. */
  52. void rc_buildreq(SEND_DATA *data, int code, char *server, unsigned short port,
  53. int timeout, int retries)
  54. {
  55. data->server = server;
  56. data->svc_port = port;
  57. data->seq_nbr = rc_get_seqnbr();
  58. data->timeout = timeout;
  59. data->retries = retries;
  60. data->code = code;
  61. }
  62. /*
  63. * Function: rc_guess_seqnbr
  64. *
  65. * Purpose: return a random sequence number
  66. *
  67. */
  68. static unsigned char rc_guess_seqnbr(void)
  69. {
  70. return (unsigned char)(magic() & UCHAR_MAX);
  71. }
  72. /*
  73. * Function: rc_get_seqnbr
  74. *
  75. * Purpose: generate a sequence number
  76. *
  77. */
  78. unsigned char rc_get_seqnbr(void)
  79. {
  80. FILE *sf;
  81. int tries = 1;
  82. int seq_nbr, pos;
  83. char *seqfile = rc_conf_str("seqfile");
  84. if ((sf = fopen(seqfile, "a+")) == NULL)
  85. {
  86. error("rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile, strerror(errno));
  87. /* well, so guess a sequence number */
  88. return rc_guess_seqnbr();
  89. }
  90. while (do_lock_exclusive(fileno(sf))!= 0)
  91. {
  92. if (errno != EWOULDBLOCK) {
  93. error("rc_get_seqnbr: flock failure: %s: %s", seqfile, strerror(errno));
  94. fclose(sf);
  95. return rc_guess_seqnbr();
  96. }
  97. tries++;
  98. if (tries <= 10)
  99. rc_mdelay(500);
  100. else
  101. break;
  102. }
  103. if (tries > 10) {
  104. error("rc_get_seqnbr: couldn't get lock after %d tries: %s", tries-1, seqfile);
  105. fclose(sf);
  106. return rc_guess_seqnbr();
  107. }
  108. pos = ftell(sf);
  109. rewind(sf);
  110. if (fscanf(sf, "%d", &seq_nbr) != 1) {
  111. if (pos != ftell(sf)) {
  112. /* file was not empty */
  113. error("rc_get_seqnbr: fscanf failure: %s", seqfile);
  114. }
  115. seq_nbr = rc_guess_seqnbr();
  116. }
  117. rewind(sf);
  118. ftruncate(fileno(sf),0);
  119. fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX);
  120. fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */
  121. if (do_unlock(fileno(sf)) != 0)
  122. error("rc_get_seqnbr: couldn't release lock on %s: %s", seqfile, strerror(errno));
  123. fclose(sf);
  124. return (unsigned char)seq_nbr;
  125. }
  126. /*
  127. * Function: rc_auth
  128. *
  129. * Purpose: Builds an authentication request for port id client_port
  130. * with the value_pairs send and submits it to a server
  131. *
  132. * Returns: received value_pairs in received, messages from the server in msg
  133. * and 0 on success, negative on failure as return value
  134. *
  135. */
  136. int rc_auth(UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received,
  137. char *msg, REQUEST_INFO *info)
  138. {
  139. SERVER *authserver = rc_conf_srv("authserver");
  140. if (!authserver) {
  141. return (ERROR_RC);
  142. }
  143. return rc_auth_using_server(authserver, client_port, send, received,
  144. msg, info);
  145. }
  146. /*
  147. * Function: rc_auth_using_server
  148. *
  149. * Purpose: Builds an authentication request for port id client_port
  150. * with the value_pairs send and submits it to a server. You
  151. * explicitly supply a server list.
  152. *
  153. * Returns: received value_pairs in received, messages from the server in msg
  154. * and 0 on success, negative on failure as return value
  155. *
  156. */
  157. int rc_auth_using_server(SERVER *authserver,
  158. UINT4 client_port,
  159. VALUE_PAIR *send,
  160. VALUE_PAIR **received,
  161. char *msg, REQUEST_INFO *info)
  162. {
  163. SEND_DATA data;
  164. int result;
  165. int i;
  166. int timeout = rc_conf_int("radius_timeout");
  167. int retries = rc_conf_int("radius_retries");
  168. data.send_pairs = send;
  169. data.receive_pairs = NULL;
  170. /*
  171. * Fill in NAS-IP-Address or NAS-Identifier
  172. */
  173. if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
  174. return (ERROR_RC);
  175. /*
  176. * Fill in NAS-Port
  177. */
  178. if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
  179. return (ERROR_RC);
  180. result = ERROR_RC;
  181. for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
  182. ; i++)
  183. {
  184. if (data.receive_pairs != NULL) {
  185. rc_avpair_free(data.receive_pairs);
  186. data.receive_pairs = NULL;
  187. }
  188. rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
  189. authserver->port[i], timeout, retries);
  190. result = rc_send_server (&data, msg, info);
  191. }
  192. *received = data.receive_pairs;
  193. return result;
  194. }
  195. /*
  196. * Function: rc_auth_proxy
  197. *
  198. * Purpose: Builds an authentication request
  199. * with the value_pairs send and submits it to a server.
  200. * Works for a proxy; does not add IP address, and does
  201. * does not rely on config file.
  202. *
  203. * Returns: received value_pairs in received, messages from the server in msg
  204. * and 0 on success, negative on failure as return value
  205. *
  206. */
  207. int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
  208. {
  209. SEND_DATA data;
  210. int result;
  211. int i;
  212. SERVER *authserver = rc_conf_srv("authserver");
  213. int timeout = rc_conf_int("radius_timeout");
  214. int retries = rc_conf_int("radius_retries");
  215. data.send_pairs = send;
  216. data.receive_pairs = NULL;
  217. result = ERROR_RC;
  218. for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
  219. ; i++)
  220. {
  221. if (data.receive_pairs != NULL) {
  222. rc_avpair_free(data.receive_pairs);
  223. data.receive_pairs = NULL;
  224. }
  225. rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
  226. authserver->port[i], timeout, retries);
  227. result = rc_send_server (&data, msg, NULL);
  228. }
  229. *received = data.receive_pairs;
  230. return result;
  231. }
  232. /*
  233. * Function: rc_acct_using_server
  234. *
  235. * Purpose: Builds an accounting request for port id client_port
  236. * with the value_pairs send. You explicitly supply server list.
  237. *
  238. * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
  239. * filled in by this function, the rest has to be supplied.
  240. */
  241. int rc_acct_using_server(SERVER *acctserver,
  242. UINT4 client_port,
  243. VALUE_PAIR *send)
  244. {
  245. SEND_DATA data;
  246. VALUE_PAIR *adt_vp;
  247. int result;
  248. time_t start_time, dtime;
  249. char msg[4096];
  250. int i;
  251. int timeout = rc_conf_int("radius_timeout");
  252. int retries = rc_conf_int("radius_retries");
  253. data.send_pairs = send;
  254. data.receive_pairs = NULL;
  255. /*
  256. * Fill in NAS-IP-Address or NAS-Identifier
  257. */
  258. if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
  259. return (ERROR_RC);
  260. /*
  261. * Fill in NAS-Port
  262. */
  263. if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
  264. return (ERROR_RC);
  265. /*
  266. * Fill in Acct-Delay-Time
  267. */
  268. dtime = 0;
  269. if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
  270. return (ERROR_RC);
  271. start_time = time(NULL);
  272. result = ERROR_RC;
  273. for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
  274. ; i++)
  275. {
  276. if (data.receive_pairs != NULL) {
  277. rc_avpair_free(data.receive_pairs);
  278. data.receive_pairs = NULL;
  279. }
  280. rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
  281. acctserver->port[i], timeout, retries);
  282. dtime = time(NULL) - start_time;
  283. rc_avpair_assign(adt_vp, &dtime, 0);
  284. result = rc_send_server (&data, msg, NULL);
  285. }
  286. rc_avpair_free(data.receive_pairs);
  287. return result;
  288. }
  289. /*
  290. * Function: rc_acct
  291. *
  292. * Purpose: Builds an accounting request for port id client_port
  293. * with the value_pairs send
  294. *
  295. * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
  296. * filled in by this function, the rest has to be supplied.
  297. */
  298. int rc_acct(UINT4 client_port, VALUE_PAIR *send)
  299. {
  300. SERVER *acctserver = rc_conf_srv("acctserver");
  301. if (!acctserver) return (ERROR_RC);
  302. return rc_acct_using_server(acctserver, client_port, send);
  303. }
  304. /*
  305. * Function: rc_acct_proxy
  306. *
  307. * Purpose: Builds an accounting request with the value_pairs send
  308. *
  309. */
  310. int rc_acct_proxy(VALUE_PAIR *send)
  311. {
  312. SEND_DATA data;
  313. int result;
  314. char msg[4096];
  315. int i;
  316. SERVER *acctserver = rc_conf_srv("authserver");
  317. int timeout = rc_conf_int("radius_timeout");
  318. int retries = rc_conf_int("radius_retries");
  319. data.send_pairs = send;
  320. data.receive_pairs = NULL;
  321. result = ERROR_RC;
  322. for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
  323. ; i++)
  324. {
  325. if (data.receive_pairs != NULL) {
  326. rc_avpair_free(data.receive_pairs);
  327. data.receive_pairs = NULL;
  328. }
  329. rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
  330. acctserver->port[i], timeout, retries);
  331. result = rc_send_server (&data, msg, NULL);
  332. }
  333. rc_avpair_free(data.receive_pairs);
  334. return result;
  335. }
  336. /*
  337. * Function: rc_check
  338. *
  339. * Purpose: ask the server hostname on the specified port for a
  340. * status message
  341. *
  342. */
  343. int rc_check(char *host, unsigned short port, char *msg)
  344. {
  345. SEND_DATA data;
  346. int result;
  347. UINT4 service_type;
  348. int timeout = rc_conf_int("radius_timeout");
  349. int retries = rc_conf_int("radius_retries");
  350. data.send_pairs = data.receive_pairs = NULL;
  351. /*
  352. * Fill in NAS-IP-Address or NAS-Identifier,
  353. * although it isn't neccessary
  354. */
  355. if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
  356. return (ERROR_RC);
  357. /*
  358. * Fill in Service-Type
  359. */
  360. service_type = PW_ADMINISTRATIVE;
  361. rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
  362. rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
  363. result = rc_send_server (&data, msg, NULL);
  364. rc_avpair_free(data.receive_pairs);
  365. return result;
  366. }