00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #include <net-snmp/net-snmp-config.h>
00081
00082 #include <stdio.h>
00083 #include <sys/types.h>
00084 #include <ctype.h>
00085 #include <errno.h>
00086
00087 #if HAVE_STRING_H
00088 #include <string.h>
00089 #else
00090 #include <strings.h>
00091 #endif
00092 #if HAVE_STDLIB_H
00093 #include <stdlib.h>
00094 #endif
00095 #if HAVE_UNISTD_H
00096 #include <unistd.h>
00097 #endif
00098 #if HAVE_SYS_SOCKET_H
00099 #include <sys/socket.h>
00100 #endif
00101 #if HAVE_NETINET_IN_H
00102 #include <netinet/in.h>
00103 #endif
00104 #if HAVE_ARPA_INET_H
00105 #include <arpa/inet.h>
00106 #endif
00107 #if HAVE_NETDB_H
00108 #include <netdb.h>
00109 #endif
00110 #if HAVE_SYS_UIO_H
00111 #include <sys/uio.h>
00112 #endif
00113
00114 #if HAVE_WINSOCK_H
00115 #include <winsock2.h>
00116 #include <ws2tcpip.h>
00117 #endif
00118
00119 #if HAVE_DMALLOC_H
00120 #include <dmalloc.h>
00121 #endif
00122
00123 #include <net-snmp/types.h>
00124 #include <net-snmp/output_api.h>
00125 #include <net-snmp/config_api.h>
00126
00127 #include <net-snmp/library/snmp_transport.h>
00128 #include <net-snmp/library/snmpDTLSUDPDomain.h>
00129 #include <net-snmp/library/snmpUDPDomain.h>
00130 #include <net-snmp/library/system.h>
00131 #include <net-snmp/library/tools.h>
00132 #include <net-snmp/library/snmp_openssl.h>
00133 #include <net-snmp/library/callback.h>
00134
00135 #include "openssl/bio.h"
00136 #include "openssl/ssl.h"
00137 #include "openssl/err.h"
00138
00139 #ifndef INADDR_NONE
00140 #define INADDR_NONE -1
00141 #endif
00142
00143 #ifdef MSG_DONTWAIT
00144 #define NETSNMP_DONTWAIT MSG_DONTWAIT
00145 #else
00146 #define NETSNMP_DONTWAIT 0
00147 #endif
00148
00149 #define WE_ARE_SERVER 0
00150 #define WE_ARE_CLIENT 1
00151
00152 oid netsnmpDTLSUDPDomain[] = { TRANSPORT_DOMAIN_DTLS_UDP_IP };
00153 size_t netsnmpDTLSUDPDomain_len = OID_LENGTH(netsnmpDTLSUDPDomain);
00154
00155 static netsnmp_tdomain dtlsudpDomain;
00156
00157
00158
00159
00160 typedef struct bio_cache_s {
00161 BIO *bio;
00162 BIO *write_bio;
00163 struct sockaddr_in sockaddr;
00164 uint32_t ipv4addr;
00165 u_short portnum;
00166 SSL *con;
00167 SSL_CTX *ctx;
00168 struct bio_cache_s *next;
00169 int msgnum;
00170 int sock;
00171 char *securityName;
00172 } bio_cache;
00173
00174 bio_cache *biocache = NULL;
00175
00176
00177
00178
00179
00180
00181 SSL_CTX *client_ctx, *server_ctx;
00182
00183
00184
00185
00186
00187
00188 static bio_cache *find_bio_cache(struct sockaddr_in *from_addr) {
00189 bio_cache *cachep = NULL;
00190 cachep = biocache;
00191 while(cachep) {
00192
00193 if (cachep->ipv4addr == from_addr->sin_addr.s_addr &&
00194 cachep->portnum == from_addr->sin_port) {
00195
00196 break;
00197 }
00198
00199 cachep = cachep->next;
00200 }
00201 return cachep;
00202 }
00203
00204 static const char * _x509_get_error(int x509failvalue, const char *location) {
00205 static const char *reason = NULL;
00206
00207
00208
00209 switch (x509failvalue) {
00210 case X509_V_OK:
00211 reason = "X509_V_OK";
00212 break;
00213 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00214 reason = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT";
00215 break;
00216 case X509_V_ERR_UNABLE_TO_GET_CRL:
00217 reason = "X509_V_ERR_UNABLE_TO_GET_CRL";
00218 break;
00219 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
00220 reason = "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE";
00221 break;
00222 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
00223 reason = "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE";
00224 break;
00225 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
00226 reason = "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY";
00227 break;
00228 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
00229 reason = "X509_V_ERR_CERT_SIGNATURE_FAILURE";
00230 break;
00231 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
00232 reason = "X509_V_ERR_CRL_SIGNATURE_FAILURE";
00233 break;
00234 case X509_V_ERR_CERT_NOT_YET_VALID:
00235 reason = "X509_V_ERR_CERT_NOT_YET_VALID";
00236 break;
00237 case X509_V_ERR_CERT_HAS_EXPIRED:
00238 reason = "X509_V_ERR_CERT_HAS_EXPIRED";
00239 break;
00240 case X509_V_ERR_CRL_NOT_YET_VALID:
00241 reason = "X509_V_ERR_CRL_NOT_YET_VALID";
00242 break;
00243 case X509_V_ERR_CRL_HAS_EXPIRED:
00244 reason = "X509_V_ERR_CRL_HAS_EXPIRED";
00245 break;
00246 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00247 reason = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD";
00248 break;
00249 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00250 reason = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD";
00251 break;
00252 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
00253 reason = "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD";
00254 break;
00255 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
00256 reason = "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD";
00257 break;
00258 case X509_V_ERR_OUT_OF_MEM:
00259 reason = "X509_V_ERR_OUT_OF_MEM";
00260 break;
00261 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
00262 reason = "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT";
00263 break;
00264 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
00265 reason = "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN";
00266 break;
00267 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
00268 reason = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY";
00269 break;
00270 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
00271 reason = "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE";
00272 break;
00273 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
00274 reason = "X509_V_ERR_CERT_CHAIN_TOO_LONG";
00275 break;
00276 case X509_V_ERR_CERT_REVOKED:
00277 reason = "X509_V_ERR_CERT_REVOKED";
00278 break;
00279 case X509_V_ERR_INVALID_CA:
00280 reason = "X509_V_ERR_INVALID_CA";
00281 break;
00282 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
00283 reason = "X509_V_ERR_PATH_LENGTH_EXCEEDED";
00284 break;
00285 case X509_V_ERR_INVALID_PURPOSE:
00286 reason = "X509_V_ERR_INVALID_PURPOSE";
00287 break;
00288 case X509_V_ERR_CERT_UNTRUSTED:
00289 reason = "X509_V_ERR_CERT_UNTRUSTED";
00290 break;
00291 case X509_V_ERR_CERT_REJECTED:
00292 reason = "X509_V_ERR_CERT_REJECTED";
00293 break;
00294 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
00295 reason = "X509_V_ERR_SUBJECT_ISSUER_MISMATCH";
00296 break;
00297 case X509_V_ERR_AKID_SKID_MISMATCH:
00298 reason = "X509_V_ERR_AKID_SKID_MISMATCH";
00299 break;
00300 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
00301 reason = "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH";
00302 break;
00303 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
00304 reason = "X509_V_ERR_KEYUSAGE_NO_CERTSIGN";
00305 break;
00306 case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
00307 reason = "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER";
00308 break;
00309 case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
00310 reason = "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION";
00311 break;
00312 case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
00313 reason = "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN";
00314 break;
00315 case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
00316 reason = "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION";
00317 break;
00318 case X509_V_ERR_INVALID_NON_CA:
00319 reason = "X509_V_ERR_INVALID_NON_CA";
00320 break;
00321 case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
00322 reason = "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED";
00323 break;
00324 case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
00325 reason = "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE";
00326 break;
00327 case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
00328 reason = "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED";
00329 break;
00330 case X509_V_ERR_INVALID_EXTENSION:
00331 reason = "X509_V_ERR_INVALID_EXTENSION";
00332 break;
00333 case X509_V_ERR_INVALID_POLICY_EXTENSION:
00334 reason = "X509_V_ERR_INVALID_POLICY_EXTENSION";
00335 break;
00336 case X509_V_ERR_NO_EXPLICIT_POLICY:
00337 reason = "X509_V_ERR_NO_EXPLICIT_POLICY";
00338 break;
00339 case X509_V_ERR_UNNESTED_RESOURCE:
00340 reason = "X509_V_ERR_UNNESTED_RESOURCE";
00341 break;
00342 case X509_V_ERR_APPLICATION_VERIFICATION:
00343 reason = "X509_V_ERR_APPLICATION_VERIFICATION";
00344 default:
00345 reason = "unknown failure code";
00346 }
00347
00348 return reason;
00349 }
00350
00351 int verify_callback(int ok, X509_STORE_CTX *ctx) {
00352 int err, depth;
00353 char buf[1024];
00354 X509 *thecert;
00355
00356 thecert = X509_STORE_CTX_get_current_cert(ctx);
00357 err = X509_STORE_CTX_get_error(ctx);
00358 depth = X509_STORE_CTX_get_error_depth(ctx);
00359
00360
00361
00362 X509_NAME_oneline(X509_get_subject_name(thecert), buf, sizeof(buf));
00363 DEBUGMSGTL(("dtlsudp_x509",
00364 "Cert: %s\n", buf));
00365
00366
00367 DEBUGMSGTL(("dtlsudp_x509",
00368 " verify value: %d, depth=%d, error code=%d, error string=%s\n",
00369 ok, depth, err, _x509_get_error(err, "verify callback")));
00370
00371
00372 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00373 NETSNMP_DS_LIB_ALLOW_SELF_SIGNED) &&
00374 (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT == err ||
00375 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN == err)) {
00376 DEBUGMSGTL(("dtlsudp_x509", " accepting a self-signed certificate\n"));
00377 return 1;
00378 }
00379
00380
00381 DEBUGMSGTL(("dtlsudp_x509", " returing the passed in value of %d\n", ok));
00382 return(ok);
00383 }
00384
00385 static void _openssl_log_error(int rc, SSL *con, const char *location) {
00386 const char *reason;
00387
00388 if (rc == -1) {
00389 int sslnum = SSL_get_error(con, rc);
00390
00391 switch(sslnum) {
00392 case SSL_ERROR_NONE:
00393 reason = "SSL_ERROR_NONE";
00394 break;
00395
00396 case SSL_ERROR_SSL:
00397 reason = "SSL_ERROR_SSL";
00398 break;
00399
00400 case SSL_ERROR_WANT_READ:
00401 reason = "SSL_ERROR_WANT_READ";
00402 break;
00403
00404 case SSL_ERROR_WANT_WRITE:
00405 reason = "SSL_ERROR_WANT_WRITE";
00406 break;
00407
00408 case SSL_ERROR_WANT_X509_LOOKUP:
00409 reason = "SSL_ERROR_WANT_X509_LOOKUP";
00410 break;
00411
00412 case SSL_ERROR_SYSCALL:
00413 reason = "SSL_ERROR_SYSCALL";
00414 snmp_log(LOG_ERR, "DTLS error: %s: rc=%d, sslerror = %d (%s): system_error=%d (%s)\n",
00415 location, rc, sslnum, reason, errno, strerror(errno));
00416 return;
00417
00418 case SSL_ERROR_ZERO_RETURN:
00419 reason = "SSL_ERROR_ZERO_RETURN";
00420 break;
00421
00422 case SSL_ERROR_WANT_CONNECT:
00423 reason = "SSL_ERROR_WANT_CONNECT";
00424 break;
00425
00426 case SSL_ERROR_WANT_ACCEPT:
00427 reason = "SSL_ERROR_WANT_ACCEPT";
00428 break;
00429
00430 default:
00431 reason = "unknown";
00432 }
00433
00434 snmp_log(LOG_ERR, "DTLS error: %s: rc=%d, sslerror = %d (%s)\n",
00435 location, rc, sslnum, reason);
00436 }
00437 }
00438
00439
00440 #define DIEHERE(msg) { snmp_log(LOG_ERR, "%s\n", msg); return NULL; }
00441
00442 static bio_cache *
00443 start_new_cached_connection(int sock, struct sockaddr_in *remote_addr,
00444 int we_are_client) {
00445 bio_cache *cachep = NULL;
00446
00447 if (!sock)
00448 DIEHERE("no socket passed in to start_new_cached_connection\n");
00449 if (!remote_addr)
00450 DIEHERE("no remote_addr passed in to start_new_cached_connection\n");
00451
00452 cachep = SNMP_MALLOC_TYPEDEF(bio_cache);
00453 if (!cachep)
00454 return NULL;
00455
00456 DEBUGMSGTL(("dtlsudp", "starting a new connection\n"));
00457 cachep->next = biocache;
00458 biocache = cachep;
00459
00460 cachep->ipv4addr = remote_addr->sin_addr.s_addr;
00461 cachep->portnum = remote_addr->sin_port;
00462 cachep->sock = sock;
00463 memcpy(&cachep->sockaddr, remote_addr, sizeof(*remote_addr));
00464
00465 if (we_are_client) {
00466 DEBUGMSGTL(("dtlsudp", "starting a new connection as a client to sock: %d\n", sock));
00467 cachep->con = SSL_new(client_ctx);
00468
00469
00470
00471
00472
00473 cachep->bio = BIO_new(BIO_s_mem());
00474 cachep->write_bio = BIO_new(BIO_s_mem());
00475
00476 BIO_set_mem_eof_return(cachep->bio, -1);
00477 BIO_set_mem_eof_return(cachep->write_bio, -1);
00478
00479 SSL_set_bio(cachep->con, cachep->bio, cachep->write_bio);
00480 SSL_set_connect_state(cachep->con);
00481
00482 } else {
00483
00484
00485 cachep->bio = BIO_new(BIO_s_mem());
00486
00487 if (!cachep->bio)
00488 DIEHERE("failed to create the read bio");
00489
00490 cachep->write_bio = BIO_new(BIO_s_mem());
00491
00492 if (!cachep->write_bio) {
00493 DIEHERE("failed to create the write bio");
00494 BIO_free(cachep->bio);
00495 }
00496
00497 BIO_set_mem_eof_return(cachep->bio, -1);
00498 BIO_set_mem_eof_return(cachep->write_bio, -1);
00499
00500 cachep->con = SSL_new(server_ctx);
00501
00502 if (!cachep->con) {
00503 BIO_free(cachep->bio);
00504 BIO_free(cachep->write_bio);
00505 DIEHERE("failed to create the write bio");
00506 }
00507
00508
00509
00510 SSL_set_options(cachep->con, SSL_OP_COOKIE_EXCHANGE);
00511
00512
00513
00514 SSL_set_bio(cachep->con, cachep->bio, cachep->write_bio);
00515 SSL_set_accept_state(cachep->con);
00516
00517 }
00518
00519 return cachep;
00520 }
00521
00522 static bio_cache *
00523 find_or_create_bio_cache(int sock, struct sockaddr_in *from_addr,
00524 int we_are_client) {
00525 bio_cache *cachep = find_bio_cache(from_addr);
00526 if (NULL == cachep) {
00527
00528 cachep = start_new_cached_connection(sock, from_addr, we_are_client);
00529 if (NULL == cachep) {
00530 snmp_log(LOG_ERR, "failed to open a new dtls connection\n");
00531 }
00532 }
00533 return cachep;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542 static int
00543 netsnmp_dtlsudp_recv(netsnmp_transport *t, void *buf, int size,
00544 void **opaque, int *olength)
00545 {
00546 int rc = -1;
00547 socklen_t fromlen = sizeof(struct sockaddr);
00548 netsnmp_addr_pair *addr_pair = NULL;
00549 struct sockaddr *from;
00550 netsnmp_tmStateReference *tmStateRef = NULL;
00551 X509 *peer;
00552
00553 if (t != NULL && t->sock >= 0) {
00554
00555 tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference);
00556
00557 if (tmStateRef == NULL) {
00558 *opaque = NULL;
00559 *olength = 0;
00560 return -1;
00561 }
00562
00563 addr_pair = &tmStateRef->addresses;
00564 tmStateRef->have_addresses = 1;
00565 from = (struct sockaddr *) &(addr_pair->remote_addr);
00566
00567 while (rc < 0) {
00568 #if defined(linux) && defined(IP_PKTINFO)
00569 rc = netsnmp_udp_recvfrom(t->sock, buf, size, from, &fromlen, &(addr_pair->local_addr));
00570 #else
00571 rc = recvfrom(t->sock, buf, size, NETSNMP_DONTWAIT, from, &fromlen);
00572 #endif
00573 if (rc < 0 && errno != EINTR) {
00574 break;
00575 }
00576 }
00577
00578 DEBUGMSGTL(("dtlsudp", "received %d raw bytes on way to dtls\n", rc));
00579 if (rc < 0) {
00580 DEBUGMSGTL(("dtlsudp", "recvfrom fd %d err %d (\"%s\")\n",
00581 t->sock, errno, strerror(errno)));
00582 SNMP_FREE(tmStateRef);
00583 return -1;
00584 }
00585
00586 if (rc >= 0) {
00587
00588
00589
00590
00591
00592
00593
00594
00595 bio_cache *cachep =
00596 find_or_create_bio_cache(t->sock, &addr_pair->remote_addr,
00597 WE_ARE_SERVER);
00598 if (NULL == cachep) {
00599 SNMP_FREE(tmStateRef);
00600 return -1;
00601 }
00602
00603
00604 BIO_write(cachep->bio, buf, rc);
00605
00606
00607
00608
00609
00610
00611 rc = SSL_read(cachep->con, buf, size);
00612
00613 DEBUGMSGTL(("dtlsudp", "received %d decoded bytes from dtls\n", rc));
00614
00615 if (BIO_ctrl_pending(cachep->write_bio) > 0) {
00616
00617
00618 u_char outbuf[65535];
00619 int outsize;
00620 int rc2;
00621
00622
00623
00624
00625 outsize = BIO_read(cachep->write_bio, outbuf, sizeof(outbuf));
00626 if (outsize > 0) {
00627
00628 #if defined(XXXFIXME) && defined(linux) && defined(IP_PKTINFO)
00629
00630
00631 rc2 = netsnmp_udp_sendto(cachep->sock, addr_pair->local_addr, addr_pair->remote_addr, outbuf, outsize);
00632 #else
00633 rc2 = sendto(t->sock, outbuf, outsize, 0, &cachep->sockaddr, sizeof(struct sockaddr));
00634 #endif
00635
00636 if (rc2 == -1) {
00637 snmp_log(LOG_ERR, "failed to send a DTLS specific packet\n");
00638 }
00639 }
00640 }
00641
00642 if (SSL_pending(cachep->con)) {
00643 fprintf(stderr, "ack: got here... pending\n");
00644 exit(1);
00645 }
00646
00647 if (rc == -1) {
00648 _openssl_log_error(rc, cachep->con, "SSL_read");
00649 SNMP_FREE(tmStateRef);
00650
00651 if (SSL_get_error(cachep->con, rc) == SSL_ERROR_WANT_READ)
00652 return -1;
00653 return rc;
00654 }
00655
00656 {
00657 char *str = netsnmp_udp_fmtaddr(NULL, addr_pair, sizeof(netsnmp_addr_pair));
00658 DEBUGMSGTL(("dtlsudp",
00659 "recvfrom fd %d got %d bytes (from %s)\n",
00660 t->sock, rc, str));
00661 free(str);
00662 }
00663
00664
00665 tmStateRef->transportSecurityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
00666
00667
00668 if (!cachep->securityName) {
00669 if (NULL != (peer = SSL_get_peer_certificate(cachep->con))) {
00670 X509_NAME *subname;
00671 char namebuf[1024];
00672
00673
00674 subname = X509_get_subject_name(peer);
00675 X509_NAME_get_text_by_NID(subname, NID_commonName,
00676 namebuf, sizeof(namebuf));
00677 DEBUGMSGTL(("dtlsudp", "got commonname: %s\n",
00678 namebuf));
00679 cachep->securityName = strdup(namebuf);
00680 DEBUGMSGTL(("dtlsudp", "set SecName to: %s\n",
00681 cachep->securityName));
00682 } else {
00683 SNMP_FREE(tmStateRef);
00684 return -1;
00685 }
00686 }
00687
00688
00689
00690 strncpy(tmStateRef->securityName, cachep->securityName,
00691 sizeof(tmStateRef->securityName)-1);
00692 tmStateRef->securityName[sizeof(tmStateRef->securityName)-1] = '\0';
00693 tmStateRef->securityNameLen = strlen(tmStateRef->securityName);
00694
00695 *opaque = tmStateRef;
00696 *olength = sizeof(netsnmp_tmStateReference);
00697
00698 } else {
00699 DEBUGMSGTL(("dtlsudp", "recvfrom fd %d err %d (\"%s\")\n",
00700 t->sock, errno, strerror(errno)));
00701 }
00702 }
00703 return rc;
00704 }
00705
00706
00707
00708 static int
00709 netsnmp_dtlsudp_send(netsnmp_transport *t, void *buf, int size,
00710 void **opaque, int *olength)
00711 {
00712 int rc = -1;
00713 netsnmp_addr_pair *addr_pair = NULL;
00714 struct sockaddr *to = NULL;
00715 bio_cache *cachep = NULL;
00716 netsnmp_tmStateReference *tmStateRef = NULL;
00717 u_char outbuf[65535];
00718
00719 if (opaque != NULL && *opaque != NULL &&
00720 *olength == sizeof(netsnmp_tmStateReference)) {
00721 tmStateRef = (netsnmp_tmStateReference *) *opaque;
00722
00723 if (tmStateRef->have_addresses)
00724 addr_pair = &(tmStateRef->addresses);
00725 else if (t != NULL && t->data != NULL &&
00726 t->data_length == sizeof(netsnmp_addr_pair))
00727 addr_pair = (netsnmp_addr_pair *) (t->data);
00728 } else if (t != NULL && t->data != NULL &&
00729 t->data_length == sizeof(netsnmp_addr_pair)) {
00730 addr_pair = (netsnmp_addr_pair *) (t->data);
00731 }
00732
00733 if (NULL == addr_pair) {
00734 snmp_log(LOG_ERR, "dtlsudp_send: can't get address to send to\n");
00735 return -1;
00736 }
00737
00738 to = (struct sockaddr *) &(addr_pair->remote_addr);
00739
00740 if (NULL == to || NULL == t || t->sock <= 0) {
00741 snmp_log(LOG_ERR, "invalid netsnmp_dtlsudp_send usage\n");
00742 return -1;
00743 }
00744
00745
00746 if (NULL ==
00747 (cachep = find_or_create_bio_cache(t->sock, &addr_pair->remote_addr,
00748 WE_ARE_CLIENT)))
00749 return -1;
00750
00751 if (!cachep->securityName && tmStateRef && tmStateRef->securityNameLen > 0)
00752 cachep->securityName = strdup(tmStateRef->securityName);
00753
00754
00755 {
00756 char *str = netsnmp_udp_fmtaddr(NULL, (void *) addr_pair,
00757 sizeof(netsnmp_addr_pair));
00758 DEBUGMSGTL(("dtlsudp", "send %d bytes from %p to %s on fd %d\n",
00759 size, buf, str, t->sock));
00760 free(str);
00761 }
00762 rc = SSL_write(cachep->con, buf, size);
00763 if (rc < 0) {
00764 _openssl_log_error(rc, cachep->con, "SSL_write");
00765 }
00766
00767
00768
00769 rc = BIO_read(cachep->write_bio, outbuf, sizeof(outbuf));
00770 if (rc <= 0) {
00771
00772 return 0;
00773 }
00774 #if defined(FIXME) && defined(linux) && defined(IP_PKTINFO)
00775
00776
00777 rc = netsnmp_udp_sendto(cachep->sock, &cachep->sockaddr remote addr_pair ? &(addr_pair->local_addr) : NULL, to, outbuf, rc);
00778 #else
00779 rc = sendto(t->sock, outbuf, rc, 0, &cachep->sockaddr, sizeof(struct sockaddr));
00780 #endif
00781
00782 return rc;
00783 }
00784
00785
00786
00787 static int
00788 netsnmp_dtlsudp_close(netsnmp_transport *t)
00789 {
00790 int rc = -1;
00791
00792 if (t->sock >= 0) {
00793 #ifndef HAVE_CLOSESOCKET
00794 rc = close(t->sock);
00795 #else
00796 rc = closesocket(t->sock);
00797 #endif
00798 t->sock = -1;
00799 }
00800 return rc;
00801 }
00802
00803
00804
00805
00806
00807
00808
00809 netsnmp_transport *
00810 netsnmp_dtlsudp_transport(struct sockaddr_in *addr, int local)
00811 {
00812 netsnmp_transport *t = NULL;
00813 int rc = 0;
00814 char *str = NULL;
00815 char *client_socket = NULL;
00816 netsnmp_addr_pair addr_pair;
00817
00818 if (addr == NULL || addr->sin_family != AF_INET) {
00819 return NULL;
00820 }
00821
00822 memset(&addr_pair, 0, sizeof(netsnmp_addr_pair));
00823 memcpy(&(addr_pair.remote_addr), addr, sizeof(struct sockaddr_in));
00824
00825 t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
00826 if (t == NULL) {
00827 return NULL;
00828 }
00829
00830 str = netsnmp_udp_fmtaddr(NULL, (void *)&addr_pair,
00831 sizeof(netsnmp_addr_pair));
00832 DEBUGMSGTL(("dtlsudp", "open %s %s\n", local ? "local" : "remote",
00833 str));
00834 free(str);
00835
00836 t->domain = netsnmpDTLSUDPDomain;
00837 t->domain_length = netsnmpDTLSUDPDomain_len;
00838
00839 t->sock = socket(PF_INET, SOCK_DGRAM, 0);
00840 DEBUGMSGTL(("dtlsudp", "openned socket %d as local=%d\n", t->sock,
00841 local));
00842 if (t->sock < 0) {
00843 netsnmp_transport_free(t);
00844 return NULL;
00845 }
00846
00847
00848
00849 _netsnmp_udp_sockopt_set(t->sock, local);
00850
00851 if (local) {
00852
00853
00854
00855
00856
00857
00858 t->local = (u_char *) malloc(6);
00859 if (t->local == NULL) {
00860 netsnmp_transport_free(t);
00861 return NULL;
00862 }
00863 memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
00864 t->local[4] = (htons(addr->sin_port) & 0xff00) >> 8;
00865 t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
00866 t->local_length = 6;
00867
00868 #if defined(linux) && defined(IP_PKTINFO)
00869 {
00870 int sockopt = 1;
00871 if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof sockopt) == -1) {
00872 DEBUGMSGTL(("dtlsudp", "couldn't set IP_PKTINFO: %s\n",
00873 strerror(errno)));
00874 netsnmp_transport_free(t);
00875 return NULL;
00876 }
00877 DEBUGMSGTL(("dtlsudp", "set IP_PKTINFO\n"));
00878 }
00879 #endif
00880 rc = bind(t->sock, (struct sockaddr *) addr,
00881 sizeof(struct sockaddr));
00882 if (rc != 0) {
00883 netsnmp_dtlsudp_close(t);
00884 netsnmp_transport_free(t);
00885 return NULL;
00886 }
00887 t->data = NULL;
00888 t->data_length = 0;
00889 } else {
00890
00891
00892
00893
00894
00895 client_socket = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00896 NETSNMP_DS_LIB_CLIENT_ADDR);
00897 if (client_socket) {
00898 struct sockaddr_in client_addr;
00899 netsnmp_sockaddr_in2(&client_addr, client_socket, NULL);
00900 addr_pair.local_addr = client_addr.sin_addr;
00901 client_addr.sin_port = 0;
00902 DEBUGMSGTL(("dtlsudp", "binding socket: %d\n", t->sock));
00903 rc = bind(t->sock, (struct sockaddr *)&client_addr,
00904 sizeof(struct sockaddr));
00905 if ( rc != 0 ) {
00906 DEBUGMSGTL(("dtlsudp", "failed to bind for clientaddr: %d %s\n",
00907 errno, strerror(errno)));
00908 netsnmp_dtlsudp_close(t);
00909 netsnmp_transport_free(t);
00910 return NULL;
00911 }
00912 }
00913
00914 str = netsnmp_udp_fmtaddr(NULL, (void *)&addr_pair,
00915 sizeof(netsnmp_addr_pair));
00916 DEBUGMSGTL(("dtlsudp", "client open %s\n", str));
00917 free(str);
00918
00919
00920
00921
00922
00923
00924 t->data = SNMP_MALLOC_TYPEDEF(netsnmp_addr_pair);
00925 t->remote = (u_char *)malloc(6);
00926 if (t->data == NULL || t->remote == NULL) {
00927 netsnmp_transport_free(t);
00928 return NULL;
00929 }
00930 memcpy(t->remote, (u_char *) & (addr->sin_addr.s_addr), 4);
00931 t->remote[4] = (htons(addr->sin_port) & 0xff00) >> 8;
00932 t->remote[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
00933 t->remote_length = 6;
00934 memcpy(t->data, &addr_pair, sizeof(netsnmp_addr_pair));
00935 t->data_length = sizeof(netsnmp_addr_pair);
00936
00937
00938 if (connect(t->sock, (struct sockaddr *) addr, sizeof(*addr)) == -1)
00939 snmp_log(LOG_ERR, "dtls: failed to connect\n");
00940
00941 }
00942
00943
00944
00945
00946
00947 t->msgMaxSize = 0xffff - 8 - 20;
00948 t->f_recv = netsnmp_dtlsudp_recv;
00949 t->f_send = netsnmp_dtlsudp_send;
00950 t->f_close = netsnmp_dtlsudp_close;
00951 t->f_accept = NULL;
00952 t->f_fmtaddr = netsnmp_udp_fmtaddr;
00953 t->flags = NETSNMP_TRANSPORT_FLAG_TUNNELED;
00954
00955 return t;
00956 }
00957
00958
00959 void
00960 netsnmp_dtlsudp_agent_config_tokens_register(void)
00961 {
00962 }
00963
00964
00965
00966
00967 netsnmp_transport *
00968 netsnmp_dtlsudp_create_tstring(const char *str, int local,
00969 const char *default_target)
00970 {
00971 struct sockaddr_in addr;
00972
00973 if (netsnmp_sockaddr_in2(&addr, str, default_target)) {
00974 return netsnmp_dtlsudp_transport(&addr, local);
00975 } else {
00976 return NULL;
00977 }
00978 }
00979
00980
00981 netsnmp_transport *
00982 netsnmp_dtlsudp_create_ostring(const u_char * o, size_t o_len, int local)
00983 {
00984 struct sockaddr_in addr;
00985
00986 if (o_len == 6) {
00987 unsigned short porttmp = (o[4] << 8) + o[5];
00988 addr.sin_family = AF_INET;
00989 memcpy((u_char *) & (addr.sin_addr.s_addr), o, 4);
00990 addr.sin_port = htons(porttmp);
00991 return netsnmp_dtlsudp_transport(&addr, local);
00992 }
00993 return NULL;
00994 }
00995
00996 #define LOGANDDIE(msg) { snmp_log(LOG_ERR, "%s\n", msg); return 0; }
00997
00998 static int have_done_init = 0;
00999
01000 static int
01001 dtlsudp_bootstrap(int majorid, int minorid, void *serverarg, void *clientarg) {
01002 const char *certfile;
01003 EVP_PKEY *key = NULL;
01004 X509 *cert = NULL;
01005 BIO *keybio = NULL;
01006
01007
01008 if (have_done_init)
01009 return 0;
01010 have_done_init = 1;
01011
01012
01013
01014
01015 client_ctx = SSL_CTX_new(DTLSv1_client_method());
01016 if (!client_ctx) {
01017 LOGANDDIE("can't create a new context");
01018 }
01019 SSL_CTX_set_read_ahead (client_ctx, 1);
01020
01021 SSL_CTX_set_verify(client_ctx,
01022 SSL_VERIFY_PEER|
01023 SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
01024 SSL_VERIFY_CLIENT_ONCE,
01025 &verify_callback);
01026
01027 keybio = BIO_new(BIO_s_file());
01028 if (!keybio)
01029 LOGANDDIE ("error creating bio for reading public key");
01030
01031 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01032 NETSNMP_DS_LIB_X509_CLIENT_PUB);
01033
01034 DEBUGMSGTL(("dtlsudp", "using public key: %s\n", certfile));
01035 if (BIO_read_filename(keybio, certfile) <=0)
01036 LOGANDDIE ("error reading public key");
01037
01038 cert = PEM_read_bio_X509_AUX(keybio, NULL, NULL, NULL);
01039 if (!cert)
01040 LOGANDDIE("failed to load public key");
01041
01042
01043
01044 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01045 NETSNMP_DS_LIB_X509_CLIENT_PRIV);
01046
01047 keybio = BIO_new(BIO_s_file());
01048 if (!keybio)
01049 LOGANDDIE ("error creating bio for reading private key");
01050
01051 DEBUGMSGTL(("dtlsudp", "using private key: %s\n", certfile));
01052 if (!keybio ||
01053 BIO_read_filename(keybio, certfile) <= 0)
01054 LOGANDDIE ("error reading private key");
01055
01056 key = PEM_read_bio_PrivateKey(keybio, NULL, NULL, NULL);
01057
01058 if (!key)
01059 LOGANDDIE("failed to load private key");
01060
01061
01062 if (SSL_CTX_use_certificate(client_ctx, cert) <= 0)
01063 LOGANDDIE("failed to set the certificate to use");
01064
01065 if (SSL_CTX_use_PrivateKey(client_ctx, key) <= 0)
01066 LOGANDDIE("failed to set the private key to use");
01067
01068 if (!SSL_CTX_check_private_key(client_ctx))
01069 LOGANDDIE("public and private keys incompatible");
01070
01071
01072 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01073 NETSNMP_DS_LIB_X509_SERVER_CERTS);
01074
01075
01076
01077 if(! SSL_CTX_load_verify_locations(client_ctx, certfile, NULL)) {
01078 LOGANDDIE("failed to load truststore");
01079
01080 }
01081
01082 if (!SSL_CTX_set_default_verify_paths(client_ctx)) {
01083 LOGANDDIE ("failed to set default verify path");
01084 }
01085
01086
01087
01088
01089
01090 server_ctx = SSL_CTX_new(DTLSv1_server_method());
01091 if (!server_ctx) {
01092 LOGANDDIE("can't create a new context");
01093 }
01094
01095 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01096 NETSNMP_DS_LIB_X509_SERVER_PUB);
01097
01098 if (SSL_CTX_use_certificate_file(server_ctx, certfile,
01099 SSL_FILETYPE_PEM) < 1) {
01100 LOGANDDIE("faild to load cert");
01101 }
01102
01103 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01104 NETSNMP_DS_LIB_X509_SERVER_PRIV);
01105
01106 if (SSL_CTX_use_PrivateKey_file(server_ctx, certfile, SSL_FILETYPE_PEM) < 1) {
01107 LOGANDDIE("faild to load key");
01108 }
01109
01110 SSL_CTX_set_read_ahead(server_ctx, 1);
01111
01112
01113 certfile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
01114 NETSNMP_DS_LIB_X509_CLIENT_CERTS);
01115 if(! SSL_CTX_load_verify_locations(server_ctx, certfile, NULL)) {
01116 LOGANDDIE("failed to load truststore");
01117
01118 }
01119
01120 SSL_CTX_set_verify(server_ctx,
01121 SSL_VERIFY_PEER|
01122 SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
01123 SSL_VERIFY_CLIENT_ONCE,
01124 &verify_callback);
01125
01126 return 0;
01127 }
01128
01129
01130 void
01131 netsnmp_dtlsudp_ctor(void)
01132 {
01133 DEBUGMSGTL(("dtlsudp", "registering DTLS constructor\n"));
01134
01135
01136
01137
01138 netsnmp_init_openssl();
01139
01140
01141
01142
01143
01144
01145 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ServerCerts",
01146 NETSNMP_DS_LIBRARY_ID,
01147 NETSNMP_DS_LIB_X509_SERVER_CERTS);
01148
01149
01150 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ClientPub",
01151 NETSNMP_DS_LIBRARY_ID,
01152 NETSNMP_DS_LIB_X509_CLIENT_PUB);
01153
01154
01155 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ClientPriv",
01156 NETSNMP_DS_LIBRARY_ID,
01157 NETSNMP_DS_LIB_X509_CLIENT_PRIV);
01158
01159
01160
01161
01162
01163
01164 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ClientCerts",
01165 NETSNMP_DS_LIBRARY_ID,
01166 NETSNMP_DS_LIB_X509_CLIENT_CERTS);
01167
01168
01169 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ServerPub",
01170 NETSNMP_DS_LIBRARY_ID,
01171 NETSNMP_DS_LIB_X509_SERVER_PUB);
01172
01173 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defX509ServerPriv",
01174 NETSNMP_DS_LIBRARY_ID,
01175 NETSNMP_DS_LIB_X509_SERVER_PRIV);
01176
01177 netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "AllowSelfSignedX509",
01178 NETSNMP_DS_LIBRARY_ID,
01179 NETSNMP_DS_LIB_ALLOW_SELF_SIGNED);
01180
01181
01182
01183
01184 snmp_register_callback(SNMP_CALLBACK_LIBRARY,
01185 SNMP_CALLBACK_POST_READ_CONFIG,
01186 dtlsudp_bootstrap, NULL);
01187
01188 dtlsudpDomain.name = netsnmpDTLSUDPDomain;
01189 dtlsudpDomain.name_length = netsnmpDTLSUDPDomain_len;
01190 dtlsudpDomain.prefix = (const char**)calloc(2, sizeof(char *));
01191 dtlsudpDomain.prefix[0] = "dtlsudp";
01192
01193 dtlsudpDomain.f_create_from_tstring_new = netsnmp_dtlsudp_create_tstring;
01194 dtlsudpDomain.f_create_from_ostring = netsnmp_dtlsudp_create_ostring;
01195
01196 netsnmp_tdomain_register(&dtlsudpDomain);
01197 }