dnet.c
上传用户:knt0001
上传日期:2022-01-28
资源大小:264k
文件大小:8k
源码类别:

Email客户端

开发平台:

C/C++

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <assert.h>
  6. #include <sys/utsname.h>
  7. #include <sys/socket.h>
  8. #include <sys/types.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #if HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14. #ifdef HAVE_LIBSSL
  15. #include <openssl/ssl.h>
  16. #include <openssl/crypto.h>
  17. #include <openssl/x509.h>
  18. #include <openssl/pem.h>
  19. #include <openssl/rand.h>
  20. #endif
  21. #include "dutil.h"
  22. #include "dnet.h"
  23. typedef struct sockaddr SA;
  24. typedef struct sockaddr_in SIN;
  25. struct socket {
  26. bool eom; /* End of Message? */
  27. int sock; /* Socket descriptor */
  28. int flags; /* Error flags */
  29. int errnum; /* Essentially, errno */
  30. int avail_bytes; /* Available bytes in buffer */
  31. char *bufptr; /* Pointer to Internal buffer */
  32. char *buf; /* The buffer. */
  33. #ifdef HAVE_LIBSSL
  34. SSL_CTX *ctx; /* OpenSSL CTX struct, used for TLS */
  35. SSL *ssl; /* OpenSSL SSL struct, used for TLS */
  36. #endif
  37. };
  38. /**
  39.  * A wrapper for gethostbyname. This allows us to figure out
  40.  * if we need to use the regular gethostbyname, the reentrant
  41.  * gethostbyname's or an IPV6 version.
  42.  *
  43.  * Params
  44.  *  name - The hostname to resolve
  45.  *  hent - A hostent struct.
  46.  *
  47.  * Return
  48.  *  ERROR upon failure to resolve name
  49.  *  SUCCESS otherwise
  50.  */
  51. int
  52. dnetResolveName(const char *name, struct hostent *hent)
  53. {
  54.         int ret = ERROR; 
  55.         struct hostent *him;
  56.         him = gethostbyname(name);
  57.         if (him) {
  58.                 memcpy(hent, him, sizeof(struct hostent));
  59.                 ret = SUCCESS;
  60.         }
  61.         return ret;
  62. }
  63. /**
  64.  * This function creates a socket connection based on a 
  65.  * hostname and port.  It will return a FILE descriptor
  66.  * so that you can perform buffered read/writes on the socket.
  67.  *
  68.  * LIMITATIONS
  69.  *  - Only opens a PF_INET socket.
  70.  *  - "hostname" must be a FQD or ascii IP address.
  71.  *
  72.  * Params
  73.  *  hostname - The FQD or IP of the host to connect to
  74.  *  port - the port to connect on.
  75.  *
  76.  * Return
  77.  *  dsocket - upon successful connection.
  78.  *  NULL - upon failure to connect.
  79.  */
  80. dsocket *
  81. dnetConnect(const char *hostname, unsigned int port)
  82. {
  83. int sd=0;
  84. SIN sin;
  85. struct hostent him;
  86. dsocket *ret = NULL;
  87. memset(&sin, 0, sizeof(SIN));
  88. memset(&him, 0, sizeof(struct hostent));
  89. if (dnetResolveName(hostname, &him) == ERROR) {
  90. return NULL;
  91. }
  92. sin.sin_family = PF_INET;
  93. sin.sin_port = htons(port);
  94. memcpy(&sin.sin_addr.s_addr, him.h_addr_list[0], 
  95. sizeof(sin.sin_addr.s_addr));
  96. sd = socket(sin.sin_family, SOCK_STREAM, 0);
  97. if (sd > 0) {
  98. if (connect(sd, (SA *)&sin, sizeof(SIN)) >= 0) {
  99. ret = xmalloc(sizeof(struct socket));
  100. ret->sock = sd;
  101. ret->buf = xmalloc(MAXSOCKBUF);
  102. ret->bufptr = ret->buf;
  103. }
  104. }
  105. return ret;
  106. }
  107. /**
  108.  * Generates a random seed used for TLS connection.
  109.  */
  110. #ifdef HAVE_LIBSSL
  111. static void
  112. _genRandomSeed(void)
  113. {
  114. struct {
  115. struct utsname uname;
  116. int uname_1;
  117. int uname_2;
  118. uid_t uid;
  119. uid_t euid;
  120. gid_t gid;
  121. gid_t egid;
  122. } data;
  123. struct {
  124. pid_t pid;
  125. time_t time;
  126. void *stack;
  127. } uniq;
  128. data.uname_1 = uname(&data.uname);
  129. data.uname_2 = errno;
  130. data.uid = getuid();
  131. data.euid = geteuid();
  132. data.gid = getgid();
  133. data.egid = getegid();
  134. RAND_seed(&data, sizeof(data));
  135. uniq.pid = getpid();
  136. uniq.time = time(NULL);
  137. uniq.stack = &uniq;
  138. RAND_seed(&uniq, sizeof(uniq));
  139. }
  140. #endif
  141. /**
  142.  * This will allow you to use TLS over an existing connection.
  143.  * Will return error if a connection has not already been established.
  144.  */
  145. int
  146. dnetUseTls(dsocket *sd)
  147. {
  148. #ifdef HAVE_LIBSSL
  149. // Can't do this unless we have a connection.
  150. if (sd->sock <= 0) {
  151. return ERROR;
  152. }
  153. SSL_load_error_strings();
  154. if (SSL_library_init() == -1) {
  155. return ERROR;
  156. }
  157. _genRandomSeed();
  158. sd->ctx = SSL_CTX_new(TLSv1_client_method());
  159. if (!sd->ctx) {
  160. return ERROR;
  161. }
  162. sd->ssl = SSL_new(sd->ctx);
  163. if (!sd->ssl) {
  164. SSL_CTX_free(sd->ctx);
  165. sd->ctx = NULL;
  166. return ERROR;
  167. }
  168. SSL_set_fd(sd->ssl, sd->sock);
  169. if (SSL_connect(sd->ssl) == -1) {
  170. SSL_CTX_free(sd->ctx);
  171. SSL_free(sd->ssl);
  172. sd->ssl = NULL;
  173. sd->ctx = NULL;
  174. return ERROR;
  175. }
  176. #else
  177. sd = sd;
  178. #endif
  179. return SUCCESS;
  180. }
  181. /**
  182.  * Simply verfies that the certificate of the peer is valid and
  183.  * that nobody is trying to fool us.
  184.  */
  185. int
  186. dnetVerifyCert(dsocket *sd)
  187. {
  188. #ifdef HAVE_LIBSSL
  189. X509 *cert = NULL;
  190. cert = SSL_get_peer_certificate(sd->ssl);
  191. if (!cert) {
  192. return ERROR;
  193. }
  194. /* TODO: Do some sort of verification here. */
  195. X509_free(cert);
  196. #else
  197. sd = sd;
  198. #endif
  199. return SUCCESS;
  200. }
  201. /**
  202.  * Close the socket connection and destroy the SOCKET structure
  203.  */
  204. void
  205. dnetClose(dsocket *sd)
  206. {
  207. if (sd) {
  208. if (sd->sock) {
  209. close(sd->sock);
  210. }
  211. #ifdef HAVE_LIBSSL
  212. if (sd->ssl) {
  213. SSL_shutdown(sd->ssl);
  214. SSL_free(sd->ssl);
  215. if (sd->ctx) {
  216. SSL_CTX_free(sd->ctx);
  217. }
  218. }
  219. #endif
  220. if (sd->buf) {
  221. xfree(sd->buf);
  222. }
  223. xfree(sd);
  224. }
  225. }
  226. /**
  227.  * This function will be similar to fgetc except it will
  228.  * use the SOCKET structure for buffering.    It will read
  229.  * up to sizeof(sd->buf) bytes into the internal buffer
  230.  * and then let sd->bufptr point to it.    If bufptr is 
  231.  * not NULL, then it will return a byte each time it is
  232.  * called and advance the pointer for the next call. If
  233.  * bufptr is NULL, it will read another sizeof(sd->buf)
  234.  * bytes and reset sd->bufptr.
  235.  */
  236. int
  237. dnetGetc(dsocket *sd)
  238. {
  239. int retval=1, recval=0;
  240. assert(sd != NULL);
  241. /* If there aren't any bytes available, get some. */
  242. if (sd->avail_bytes <= 0) {
  243. sd->eom = false;
  244. sd->flags = 0;
  245. memset(sd->buf, '', MAXSOCKBUF);
  246. #ifdef HAVE_LIBSSL
  247. if (!sd->ssl) {
  248. #endif
  249. recval = recv(sd->sock, sd->buf, MAXSOCKBUF-1, 0);
  250. #ifdef HAVE_LIBSSL
  251. } else {
  252. recval = SSL_read(sd->ssl, sd->buf, MAXSOCKBUF-1);
  253. }
  254. #endif
  255. if (recval == 0) {
  256. sd->flags |= SOCKET_EOF;
  257. retval = -1;
  258. } else if (recval == -1) {
  259. sd->flags |= SOCKET_ERROR;
  260. sd->errnum = errno;
  261. retval = -1;
  262. } else {
  263. sd->bufptr = sd->buf;
  264. sd->avail_bytes = recval;
  265. if (recval < MAXSOCKBUF-1) {
  266. // That's all they sent in this message.
  267. sd->eom = true;
  268. } else {
  269. sd->eom = false;
  270. }
  271. }
  272. if (sd->avail_bytes > 0) {
  273. sd->avail_bytes--;
  274. if (sd->avail_bytes == 0 && sd->eom) {
  275. sd->flags |= SOCKET_EOF;
  276. }
  277. retval = *sd->bufptr++;
  278. }
  279. return retval;
  280. }
  281. /**
  282.  * This function will be similar to fputc except it will
  283.  * use the SOCKET struture instead of the FILE structure
  284.  * to place the file on the stream.
  285.  */
  286. int
  287. dnetPutc(dsocket *sd, int ch)
  288. {
  289. int retval=SUCCESS;
  290. assert(sd != NULL);
  291. #ifdef HAVE_LIBSSL
  292. if (!sd->ssl) {
  293. #endif
  294. if (send(sd->sock, (char *)&ch, 1, 0) != 1) {
  295. sd->flags |= SOCKET_ERROR;
  296. sd->errnum = errno;
  297. retval = ERROR;
  298. }
  299. #ifdef HAVE_LIBSSL
  300. } else {
  301. if (SSL_write(sd->ssl, (char *)&ch, 1) == -1) {
  302. sd->flags |= SOCKET_ERROR;
  303. sd->errnum = errno;
  304. retval = ERROR;
  305. }
  306. }
  307. #endif
  308. return retval;
  309. }
  310. /**
  311.  * This function will be similar to fgets except it will
  312.  * use the Sgetc to read one character at a time.
  313.  */
  314. int
  315. dnetReadline(dsocket *sd, dstrbuf *buf)
  316. {
  317. int ch, size=0;
  318. do {
  319. ch = dnetGetc(sd);
  320. if (ch == -1) {
  321. // Error
  322. break;
  323. } else {
  324. dsbCatChar(buf, ch);
  325. size++;
  326. }
  327. } while (ch != 'n' && !dnetEof(sd));
  328. return size;
  329. }
  330. /**
  331.  * Writes to a socket
  332.  */
  333. int
  334. dnetWrite(dsocket *sd, const char *buf, size_t len)
  335. {
  336. int bytes = 0;
  337. const size_t blocklen = 4356;
  338. size_t sentLen=0;
  339. #ifdef HAVE_LIBSSL
  340. if (!sd->ssl) {
  341. #endif
  342. while (len > 0) {
  343. size_t sendSize = (len > blocklen) ? blocklen : len;
  344. bytes = send(sd->sock, buf, sendSize, 0);
  345. if (bytes == -1) {
  346. if (errno == EAGAIN) {
  347. continue;
  348. } else if (errno == EINTR) {
  349. continue;
  350. } else {
  351. sd->flags |= SOCKET_ERROR;
  352. sd->errnum = errno;
  353. break;
  354. }
  355. } else if (bytes == 0) {
  356. sd->flags |= SOCKET_ERROR;
  357. sd->errnum = EPIPE;
  358. break;
  359. } else if (bytes > 0) {
  360. buf += bytes;
  361. len -= bytes;
  362. sentLen += bytes;
  363. }
  364. }
  365. #ifdef HAVE_LIBSSL
  366. } else {
  367. sentLen = SSL_write(sd->ssl, buf, len);
  368. }
  369. #endif
  370. return sentLen;
  371. }
  372. /**
  373.  * Reads stuff from the socket up to size.
  374.  */
  375. int
  376. dnetRead(dsocket *sd, char *buf, size_t size)
  377. {
  378. u_int i;
  379. int ch;
  380. for (i = 0; i < size-1; i++) {
  381. ch = dnetGetc(sd);
  382. if (ch == -1) {
  383. i = 0;
  384. break;
  385. }
  386. *buf++ = ch;
  387. if (dnetEof(sd)) {
  388. break;
  389. }
  390. }
  391. return i;
  392. }
  393. /**
  394.  * Will test the flags for a SOCKET_ERROR 
  395.  */
  396. bool
  397. dnetErr(dsocket *sd)
  398. {
  399. return sd->flags & SOCKET_ERROR;
  400. }
  401. /**
  402.  * Will test the flags for a SOCKET_EOF
  403.  */
  404. bool
  405. dnetEof(dsocket *sd)
  406. {
  407. return sd->flags & SOCKET_EOF;
  408. }
  409. /**
  410.  * Returns the error string from the system which is
  411.  * determined by errnum (errno).
  412.  */
  413. char *
  414. dnetGetErr(dsocket *sd)
  415. {
  416. return strerror(sd->errnum);
  417. }
  418. int
  419. dnetGetSock(dsocket *sd)
  420. {
  421. return sd->sock;
  422. }