PageRenderTime 152ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/amanda/branches/amanda-252/common-src/bsdudp-security.c

#
C | 335 lines | 231 code | 32 blank | 72 comment | 37 complexity | ecafb31faf8eae940b0ff9d178d7eabd MD5 | raw file
  1. /*
  2. * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  3. * Copyright (c) 1991-1999 University of Maryland at College Park
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify, distribute, and sell this software and its
  7. * documentation for any purpose is hereby granted without fee, provided that
  8. * the above copyright notice appear in all copies and that both that
  9. * copyright notice and this permission notice appear in supporting
  10. * documentation, and that the name of U.M. not be used in advertising or
  11. * publicity pertaining to distribution of the software without specific,
  12. * written prior permission. U.M. makes no representations about the
  13. * suitability of this software for any purpose. It is provided "as is"
  14. * without express or implied warranty.
  15. *
  16. * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
  18. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. * Authors: the Amanda Development Team. Its members are listed in a
  24. * file named AUTHORS, in the root directory of this distribution.
  25. */
  26. /*
  27. * $Id: bsdudp-security.c,v 1.7 2006/07/05 13:18:20 martinea Exp $
  28. *
  29. * "BSD" security module
  30. */
  31. #include "amanda.h"
  32. #include "util.h"
  33. #include "clock.h"
  34. #include "dgram.h"
  35. #include "event.h"
  36. #include "packet.h"
  37. #include "security.h"
  38. #include "security-util.h"
  39. #include "stream.h"
  40. #include "version.h"
  41. #ifdef BSDUDP_SECURITY
  42. #ifndef SO_RCVBUF
  43. #undef DUMPER_SOCKET_BUFFERING
  44. #endif
  45. /*
  46. * Change the following from #undef to #define to cause detailed logging
  47. * of the security steps, e.g. into /tmp/amanda/amandad*debug.
  48. */
  49. #undef SHOW_SECURITY_DETAIL
  50. /*
  51. * Interface functions
  52. */
  53. static void bsdudp_connect(const char *,
  54. char *(*)(char *, void *),
  55. void (*)(void *, security_handle_t *, security_status_t), void *, void *);
  56. static void bsdudp_accept(const struct security_driver *, int, int, void (*)(security_handle_t *, pkt_t *));
  57. static void bsdudp_close(void *);
  58. /*
  59. * This is our interface to the outside world
  60. */
  61. const security_driver_t bsdudp_security_driver = {
  62. "BSDUDP",
  63. bsdudp_connect,
  64. bsdudp_accept,
  65. bsdudp_close,
  66. udpbsd_sendpkt,
  67. udp_recvpkt,
  68. udp_recvpkt_cancel,
  69. tcp1_stream_server,
  70. tcp1_stream_accept,
  71. tcp1_stream_client,
  72. tcpma_stream_close,
  73. sec_stream_auth,
  74. sec_stream_id,
  75. tcpm_stream_write,
  76. tcpm_stream_read,
  77. tcpm_stream_read_sync,
  78. tcpm_stream_read_cancel,
  79. sec_close_connection_none,
  80. NULL,
  81. NULL
  82. };
  83. /*
  84. * This is data local to the datagram socket. We have one datagram
  85. * per process, so it is global.
  86. */
  87. static udp_handle_t netfd4;
  88. static udp_handle_t netfd6;
  89. static int not_init4 = 1;
  90. static int not_init6 = 1;
  91. /* generate new handles from here */
  92. static unsigned int newhandle = 0;
  93. /*
  94. * Setup and return a handle outgoing to a client
  95. */
  96. static void
  97. bsdudp_connect(
  98. const char *hostname,
  99. char * (*conf_fn)(char *, void *),
  100. void (*fn)(void *, security_handle_t *, security_status_t),
  101. void * arg,
  102. void * datap)
  103. {
  104. struct sec_handle *bh;
  105. struct servent *se;
  106. in_port_t port;
  107. struct timeval sequence_time;
  108. amanda_timezone dontcare;
  109. int sequence;
  110. char *handle;
  111. int result;
  112. struct addrinfo hints;
  113. struct addrinfo *res = NULL;
  114. (void)conf_fn; /* Quiet unused parameter warning */
  115. (void)datap; /* Quiet unused parameter warning */
  116. assert(hostname != NULL);
  117. bh = alloc(sizeof(*bh));
  118. bh->proto_handle=NULL;
  119. bh->rc = NULL;
  120. security_handleinit(&bh->sech, &bsdudp_security_driver);
  121. #ifdef WORKING_IPV6
  122. hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL;
  123. hints.ai_family = AF_INET6;
  124. #else
  125. hints.ai_flags = AI_CANONNAME;
  126. hints.ai_family = AF_INET;
  127. #endif
  128. hints.ai_socktype = SOCK_DGRAM;
  129. hints.ai_protocol = IPPROTO_UDP;
  130. hints.ai_addrlen = 0;
  131. hints.ai_addr = NULL;
  132. hints.ai_canonname = NULL;
  133. hints.ai_next = NULL;
  134. result = getaddrinfo(hostname, NULL, &hints, &res);
  135. #ifdef WORKING_IPV6
  136. if (result != 0) {
  137. hints.ai_flags = AI_CANONNAME;
  138. hints.ai_family = AF_UNSPEC;
  139. result = getaddrinfo(hostname, NULL, &hints, &res);
  140. }
  141. #endif
  142. if(result != 0) {
  143. dbprintf(("getaddrinfo: %s\n", gai_strerror(result)));
  144. security_seterror(&bh->sech, "getaddrinfo(%s): %s\n", hostname,
  145. gai_strerror(result));
  146. (*fn)(arg, &bh->sech, S_ERROR);
  147. return;
  148. }
  149. if (res->ai_canonname == NULL) {
  150. dbprintf(("getaddrinfo(%s) did not return a canonical name\n", hostname));
  151. security_seterror(&bh->sech,
  152. _("getaddrinfo(%s) did not return a canonical name\n"), hostname);
  153. (*fn)(arg, &bh->sech, S_ERROR);
  154. return;
  155. }
  156. /*
  157. * Only init the socket once
  158. */
  159. #ifdef WORKING_IPV6
  160. if (res->ai_addr->sa_family == AF_INET6 && not_init6 == 1) {
  161. uid_t euid;
  162. dgram_zero(&netfd6.dgram);
  163. euid = geteuid();
  164. seteuid(0);
  165. dgram_bind(&netfd6.dgram, res->ai_addr->sa_family, &port);
  166. seteuid(euid);
  167. netfd6.handle = NULL;
  168. netfd6.pkt.body = NULL;
  169. netfd6.recv_security_ok = &bsd_recv_security_ok;
  170. netfd6.prefix_packet = &bsd_prefix_packet;
  171. /*
  172. * We must have a reserved port. Bomb if we didn't get one.
  173. */
  174. if (port >= IPPORT_RESERVED) {
  175. security_seterror(&bh->sech,
  176. "unable to bind to a reserved port (got port %u)",
  177. (unsigned int)port);
  178. (*fn)(arg, &bh->sech, S_ERROR);
  179. return;
  180. }
  181. not_init6 = 0;
  182. bh->udp = &netfd6;
  183. }
  184. #endif
  185. if (res->ai_addr->sa_family == AF_INET && not_init4 == 1) {
  186. uid_t euid;
  187. dgram_zero(&netfd4.dgram);
  188. euid = geteuid();
  189. seteuid((uid_t)0);
  190. dgram_bind(&netfd4.dgram, res->ai_addr->sa_family, &port);
  191. seteuid(euid);
  192. netfd4.handle = NULL;
  193. netfd4.pkt.body = NULL;
  194. netfd4.recv_security_ok = &bsd_recv_security_ok;
  195. netfd4.prefix_packet = &bsd_prefix_packet;
  196. /*
  197. * We must have a reserved port. Bomb if we didn't get one.
  198. */
  199. if (port >= IPPORT_RESERVED) {
  200. security_seterror(&bh->sech,
  201. "unable to bind to a reserved port (got port %u)",
  202. (unsigned int)port);
  203. (*fn)(arg, &bh->sech, S_ERROR);
  204. return;
  205. }
  206. not_init4 = 0;
  207. bh->udp = &netfd4;
  208. }
  209. #ifdef WORKING_IPV6
  210. if (res->ai_addr->sa_family == AF_INET6)
  211. bh->udp = &netfd6;
  212. else
  213. #endif
  214. bh->udp = &netfd4;
  215. auth_debug(1, ("Resolved hostname=%s\n", res->ai_canonname));
  216. if ((se = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL)
  217. port = AMANDA_SERVICE_DEFAULT;
  218. else
  219. port = (in_port_t)ntohs(se->s_port);
  220. amanda_gettimeofday(&sequence_time, &dontcare);
  221. sequence = (int)sequence_time.tv_sec ^ (int)sequence_time.tv_usec;
  222. handle=alloc(15);
  223. snprintf(handle,14,"000-%08x", newhandle++);
  224. if (udp_inithandle(bh->udp, bh, res->ai_canonname,
  225. (struct sockaddr_storage *)res->ai_addr, port,
  226. handle, sequence) < 0) {
  227. (*fn)(arg, &bh->sech, S_ERROR);
  228. amfree(bh->hostname);
  229. amfree(bh);
  230. } else {
  231. (*fn)(arg, &bh->sech, S_OK);
  232. }
  233. amfree(handle);
  234. freeaddrinfo(res);
  235. }
  236. /*
  237. * Setup to accept new incoming connections
  238. */
  239. static void
  240. bsdudp_accept(
  241. const struct security_driver *driver,
  242. int in,
  243. int out,
  244. void (*fn)(security_handle_t *, pkt_t *))
  245. {
  246. (void)driver; /* Quiet unused parameter warning */
  247. (void)out; /* Quiet unused parameter warning */
  248. assert(in >= 0 && out >= 0);
  249. assert(fn != NULL);
  250. /*
  251. * We assume in and out point to the same socket, and just use
  252. * in.
  253. */
  254. dgram_socket(&netfd4.dgram, in);
  255. dgram_socket(&netfd6.dgram, in);
  256. /*
  257. * Assign the function and return. When they call recvpkt later,
  258. * the recvpkt callback will call this function when it discovers
  259. * new incoming connections
  260. */
  261. netfd4.accept_fn = fn;
  262. netfd4.recv_security_ok = &bsd_recv_security_ok;
  263. netfd4.prefix_packet = &bsd_prefix_packet;
  264. netfd4.driver = &bsdudp_security_driver;
  265. udp_addref(&netfd4, &udp_netfd_read_callback);
  266. }
  267. /*
  268. * Frees a handle allocated by the above
  269. */
  270. static void
  271. bsdudp_close(
  272. void *cookie)
  273. {
  274. struct sec_handle *bh = cookie;
  275. if(bh->proto_handle == NULL) {
  276. return;
  277. }
  278. auth_debug(1, ("%s: bsdudp: close handle '%s'\n",
  279. debug_prefix_time(NULL), bh->proto_handle));
  280. udp_recvpkt_cancel(bh);
  281. if(bh->next) {
  282. bh->next->prev = bh->prev;
  283. }
  284. else {
  285. if (!not_init6 && netfd6.bh_last == bh)
  286. netfd6.bh_last = bh->prev;
  287. else
  288. netfd4.bh_last = bh->prev;
  289. }
  290. if(bh->prev) {
  291. bh->prev->next = bh->next;
  292. }
  293. else {
  294. if (!not_init6 && netfd6.bh_first == bh)
  295. netfd6.bh_first = bh->next;
  296. else
  297. netfd4.bh_first = bh->next;
  298. }
  299. amfree(bh->proto_handle);
  300. amfree(bh->hostname);
  301. amfree(bh);
  302. }
  303. #endif /* BSDUDP_SECURITY */ /* } */