00001 #include <net-snmp/net-snmp-config.h>
00002
00003 #include <stdio.h>
00004 #include <sys/types.h>
00005 #include <errno.h>
00006
00007 #include <libssh2.h>
00008 #include <libssh2_sftp.h>
00009
00010 #ifdef HAVE_SYS_PARAM_H
00011 #include <sys/param.h>
00012 #endif
00013 #if HAVE_STRING_H
00014 #include <string.h>
00015 #else
00016 #include <strings.h>
00017 #endif
00018 #if HAVE_STDLIB_H
00019 #include <stdlib.h>
00020 #endif
00021 #if HAVE_UNISTD_H
00022 #include <unistd.h>
00023 #endif
00024 #if HAVE_SYS_SOCKET_H
00025 #include <sys/socket.h>
00026 #endif
00027 #if HAVE_SYS_UN_H
00028 #include <sys/un.h>
00029 #endif
00030 #if HAVE_NETINET_IN_H
00031 #include <netinet/in.h>
00032 #endif
00033 #if HAVE_ARPA_INET_H
00034 #include <arpa/inet.h>
00035 #endif
00036 #if HAVE_FCNTL_H
00037 #include <fcntl.h>
00038 #endif
00039
00040 #if HAVE_WINSOCK_H
00041 #include <winsock2.h>
00042 #include <ws2tcpip.h>
00043 #endif
00044
00045 #if HAVE_DMALLOC_H
00046 #include <dmalloc.h>
00047 #endif
00048 #include <pwd.h>
00049
00050 #ifndef MAXPATHLEN
00051 #warn no system max path length detected
00052 #define MAXPATHLEN 2048
00053 #endif
00054
00055 #include <net-snmp/types.h>
00056 #include <net-snmp/output_api.h>
00057 #include <net-snmp/library/tools.h>
00058 #include <net-snmp/library/system.h>
00059 #include <net-snmp/library/default_store.h>
00060
00061 #include <net-snmp/library/snmp_transport.h>
00062 #include <net-snmp/library/snmpUDPDomain.h>
00063 #include <net-snmp/library/snmpTCPDomain.h>
00064 #include <net-snmp/library/snmpSSHDomain.h>
00065 #include <net-snmp/library/read_config.h>
00066
00067 #define MAX_NAME_LENGTH 127
00068
00069 #define NETSNMP_SSHTOSNMP_VERSION1 1
00070 #define NETSNMP_MAX_SSHTOSNMP_VERSION 1
00071
00072 #define DEFAULT_SOCK_NAME "sshdomainsocket"
00073
00074 typedef struct netsnmp_ssh_addr_pair_s {
00075 struct sockaddr_in remote_addr;
00076 struct in_addr local_addr;
00077 LIBSSH2_SESSION *session;
00078 LIBSSH2_CHANNEL *channel;
00079 char username[MAX_NAME_LENGTH+1];
00080 struct sockaddr_un unix_socket_end;
00081 char socket_path[MAXPATHLEN];
00082 } netsnmp_ssh_addr_pair;
00083
00084 oid netsnmp_snmpSSHDomain[] = { TRANSPORT_DOMAIN_SSH_IP };
00085 static netsnmp_tdomain sshDomain;
00086
00087 const char *keyfile1="/home/hardaker/.ssh/id_rsa.pub";
00088 const char *keyfile2="/home/hardaker/.ssh/id_rsa";
00089 const char *username="hardaker";
00090
00091 #define SNMPSSHDOMAIN_USE_EXTERNAL_PIPE 1
00092
00093
00094
00095
00096
00097 int
00098 netsnmp_sockaddr_in2(struct sockaddr_in *addr,
00099 const char *inpeername, const char *default_target);
00100
00101
00102
00103
00104
00105
00106 static char *
00107 netsnmp_ssh_fmtaddr(netsnmp_transport *t, void *data, int len)
00108 {
00109 netsnmp_ssh_addr_pair *addr_pair = NULL;
00110
00111 if (data != NULL && len == sizeof(netsnmp_ssh_addr_pair)) {
00112 addr_pair = (netsnmp_ssh_addr_pair *) data;
00113 } else if (t != NULL && t->data != NULL) {
00114 addr_pair = (netsnmp_ssh_addr_pair *) t->data;
00115 }
00116
00117 if (addr_pair == NULL) {
00118 return strdup("SSH: unknown");
00119 } else {
00120 struct sockaddr_in *to = NULL;
00121 char tmp[64];
00122 to = (struct sockaddr_in *) &(addr_pair->remote_addr);
00123 if (to == NULL) {
00124 return strdup("SSH: unknown");
00125 }
00126
00127 sprintf(tmp, "SSH: [%s]:%hd",
00128 inet_ntoa(to->sin_addr), ntohs(to->sin_port));
00129 return strdup(tmp);
00130 }
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 static int
00142 netsnmp_ssh_recv(netsnmp_transport *t, void *buf, int size,
00143 void **opaque, int *olength)
00144 {
00145 int rc = -1;
00146 netsnmp_tmStateReference *tmStateRef = NULL;
00147 netsnmp_ssh_addr_pair *addr_pair = NULL;
00148 int iamclient = 0;
00149
00150 DEBUGMSGTL(("ssh", "at the top of ssh_recv\n"));
00151 DEBUGMSGTL(("ssh", "t=%p\n", t));
00152 if (t != NULL && t->data != NULL) {
00153 addr_pair = (netsnmp_ssh_addr_pair *) t->data;
00154 }
00155
00156 DEBUGMSGTL(("ssh", "addr_pair=%p\n", addr_pair));
00157 if (t != NULL && addr_pair && addr_pair->channel) {
00158 DEBUGMSGTL(("ssh", "t=%p, addr_pair=%p, channel=%p\n",
00159 t, addr_pair, addr_pair->channel));
00160 iamclient = 1;
00161 while (rc < 0) {
00162 rc = libssh2_channel_read(addr_pair->channel, buf, size);
00163 if (rc < 0) {
00164 DEBUGMSGTL(("ssh", "recv fd %d err %d (\"%s\")\n",
00165 t->sock, errno, strerror(errno)));
00166 break;
00167 }
00168 DEBUGMSGTL(("ssh", "recv fd %d got %d bytes\n",
00169 t->sock, rc));
00170 }
00171 } else if (t != NULL) {
00172
00173 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00174
00175 socklen_t tolen = sizeof(struct sockaddr_un);
00176
00177 if (t != NULL && t->sock >= 0) {
00178 struct sockaddr *to;
00179 to = (struct sockaddr *) SNMP_MALLOC_STRUCT(sockaddr_un);
00180 if (NULL == to) {
00181 *opaque = NULL;
00182 *olength = 0;
00183 return -1;
00184 }
00185
00186 if(getsockname(t->sock, to, &tolen) != 0){
00187 free(to);
00188 *opaque = NULL;
00189 *olength = 0;
00190 return -1;
00191 };
00192
00193 if (addr_pair->username[0] == '\0') {
00194
00195 struct ucred *remoteuser;
00196 struct msghdr msg;
00197 struct iovec iov[1];
00198 char cmsg[CMSG_SPACE(sizeof(remoteuser))+4096];
00199 struct cmsghdr *cmsgptr;
00200 u_char *charbuf = buf;
00201
00202 iov[0].iov_base = buf;
00203 iov[0].iov_len = size;
00204
00205 memset(&msg, 0, sizeof msg);
00206 msg.msg_iov = iov;
00207 msg.msg_iovlen = 1;
00208 msg.msg_control = &cmsg;
00209 msg.msg_controllen = sizeof(cmsg);
00210
00211 rc = recvmsg(t->sock, &msg, MSG_DONTWAIT);
00212 if (rc <= 0) {
00213 return rc;
00214 }
00215
00216
00217 if ((u_char) charbuf[0] > NETSNMP_SSHTOSNMP_VERSION1) {
00218
00219 snmp_log(LOG_ERR, "received unsupported sshtosnmp version: %d\n", charbuf[0]);
00220 return -1;
00221 }
00222
00223 DEBUGMSGTL(("ssh", "received first msg over SSH; internal SSH protocol version %d\n", charbuf[0]));
00224
00225 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
00226 if (cmsgptr->cmsg_level == SOL_SOCKET && cmsgptr->cmsg_type == SCM_CREDENTIALS) {
00227
00228 struct passwd *user_pw;
00229
00230 remoteuser = (struct ucred *) CMSG_DATA(cmsgptr);
00231
00232 if ((user_pw = getpwuid(remoteuser->uid)) == NULL) {
00233 snmp_log(LOG_ERR, "No user found for uid %d\n",
00234 remoteuser->uid);
00235 return -1;
00236 }
00237 if (strlen(user_pw->pw_name) >
00238 sizeof(addr_pair->username)-1) {
00239 snmp_log(LOG_ERR,
00240 "User name '%s' too long for snmp\n",
00241 user_pw->pw_name);
00242 return -1;
00243 }
00244 strncpy(addr_pair->username, user_pw->pw_name,
00245 sizeof(addr_pair->username));
00246 addr_pair->username[sizeof(addr_pair->username)-1] = '\0';
00247 }
00248 DEBUGMSGTL(("ssh", "Setting user name to %s\n",
00249 addr_pair->username));
00250 }
00251
00252 if (addr_pair->username[0] == '\0') {
00253 snmp_log(LOG_ERR,
00254 "failed to extract username from sshd connected unix socket\n");
00255 return -1;
00256 }
00257
00258 if (rc == 1) {
00259
00260 t->flags |= NETSNMP_TRANSPORT_FLAG_EMPTY_PKT;
00261 return 0;
00262 }
00263
00264 rc -= 1;
00265 memmove(charbuf, &charbuf[1], rc);
00266 } else {
00267 while (rc < 0) {
00268 rc = recvfrom(t->sock, buf, size, 0, NULL, NULL);
00269 if (rc < 0 && errno != EINTR) {
00270 DEBUGMSGTL(("ssh", "recv fd %d err %d (\"%s\")\n",
00271 t->sock, errno, strerror(errno)));
00272 return rc;
00273 }
00274 *opaque = (void*)to;
00275 *olength = sizeof(struct sockaddr_un);
00276 }
00277 }
00278 DEBUGMSGTL(("ssh", "recv fd %d got %d bytes\n",
00279 t->sock, rc));
00280 }
00281
00282 #else
00283
00284 struct passwd *user_pw;
00285
00286 iamclient = 0;
00287
00288 while (rc < 0) {
00289 rc = read(STDIN_FILENO, buf, size);
00290 if (rc < 0 && errno != EINTR) {
00291 DEBUGMSGTL(("ssh",
00292 " read on stdin failed: %d (\"%s\")\n",
00293 errno, strerror(errno)));
00294 break;
00295 }
00296 if (rc == 0) {
00297
00298 DEBUGMSGTL(("ssh", "got a 0 read on stdin\n"));
00299 return -1;
00300 }
00301 DEBUGMSGTL(("ssh", "read on stdin got %d bytes\n", rc));
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 #endif
00324 }
00325
00326
00327 tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference);
00328
00329
00330
00331
00332 tmStateRef->transportSecurityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
00333
00334
00335 if (iamclient && 0) {
00336
00337
00338 strncpy(tmStateRef->securityName, addr_pair->username,
00339 sizeof(tmStateRef->securityName)-1);
00340 } else {
00341 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00342 strncpy(tmStateRef->securityName, addr_pair->username,
00343 sizeof(tmStateRef->securityName)-1);
00344 #else
00345
00346
00347
00348 if (strlen(getenv("USER")) > 127) {
00349
00350
00351 return -1;
00352 exit;
00353 }
00354
00355
00356
00357 strncpy(tmStateRef->securityName, getenv("USER"),
00358 sizeof(tmStateRef->securityName)-1);
00359 #endif
00360 }
00361 tmStateRef->securityName[sizeof(tmStateRef->securityName)-1] = '\0';
00362 tmStateRef->securityNameLen = strlen(tmStateRef->securityName);
00363 *opaque = tmStateRef;
00364 *olength = sizeof(netsnmp_tmStateReference);
00365
00366 return rc;
00367 }
00368
00369
00370
00371 static int
00372 netsnmp_ssh_send(netsnmp_transport *t, void *buf, int size,
00373 void **opaque, int *olength)
00374 {
00375 int rc = -1;
00376
00377 netsnmp_ssh_addr_pair *addr_pair = NULL;
00378 netsnmp_tmStateReference *tmStateRef = NULL;
00379
00380 if (t != NULL && t->data != NULL) {
00381 addr_pair = (netsnmp_ssh_addr_pair *) t->data;
00382 }
00383
00384 if (opaque != NULL && *opaque != NULL &&
00385 *olength == sizeof(netsnmp_tmStateReference)) {
00386 tmStateRef = (netsnmp_tmStateReference *) *opaque;
00387 }
00388
00389 if (!tmStateRef) {
00390
00391 snmp_log(LOG_ERR, "netsnmp_ssh_send wasn't passed a valid tmStateReference\n");
00392 return -1;
00393 }
00394
00395 if (NULL != t && NULL != addr_pair && NULL != addr_pair->channel) {
00396 if (addr_pair->username[0] == '\0') {
00397 strncpy(addr_pair->username, tmStateRef->securityName,
00398 sizeof(addr_pair->username)-1);
00399 addr_pair->username[sizeof(addr_pair->username)-1] = '\0';
00400 } else if (strcmp(addr_pair->username, tmStateRef->securityName) != 0 ||
00401 strlen(addr_pair->username) != tmStateRef->securityNameLen) {
00402
00403 snmp_log(LOG_ERR, "netsnmp_ssh_send was passed a tmStateReference with a securityName not equal to previous messages\n");
00404 return -1;
00405 }
00406 while (rc < 0) {
00407 rc = libssh2_channel_write(addr_pair->channel, buf, size);
00408 if (rc < 0) {
00409 break;
00410 }
00411 }
00412 } else if (t != NULL) {
00413 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00414
00415 while (rc < 0) {
00416 rc = sendto(t->sock, buf, size, 0, NULL, 0);
00417
00418 if (rc < 0 && errno != EINTR) {
00419 break;
00420 }
00421 }
00422
00423 #else
00424
00425 while (rc < 0) {
00426 rc = write(STDOUT_FILENO, buf, size);
00427 fflush(stdout);
00428 if (rc < 0 && errno != EINTR) {
00429 break;
00430 }
00431 }
00432 #endif
00433 }
00434
00435 return rc;
00436 }
00437
00438
00439
00440 static int
00441 netsnmp_ssh_close(netsnmp_transport *t)
00442 {
00443 int rc = -1;
00444 netsnmp_ssh_addr_pair *addr_pair = NULL;
00445
00446 if (t != NULL && t->data != NULL) {
00447 addr_pair = (netsnmp_ssh_addr_pair *) t->data;
00448 }
00449
00450 if (t != NULL && addr_pair && t->sock >= 0) {
00451 DEBUGMSGTL(("ssh", "close fd %d\n", t->sock));
00452
00453 if (addr_pair->channel) {
00454 libssh2_channel_close(addr_pair->channel);
00455 libssh2_channel_free(addr_pair->channel);
00456 addr_pair->channel = NULL;
00457 }
00458
00459 if (addr_pair->session) {
00460 libssh2_session_disconnect(addr_pair->session, "Normal Shutdown");
00461 libssh2_session_free(addr_pair->session);
00462 addr_pair->session = NULL;
00463 }
00464
00465 #ifndef HAVE_CLOSESOCKET
00466 rc = close(t->sock);
00467 #else
00468 rc = closesocket(t->sock);
00469 #endif
00470 t->sock = -1;
00471
00472 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00473
00474 close(t->sock);
00475
00476 if (!addr_pair->session && !addr_pair->channel) {
00477
00478 close(t->sock);
00479
00480
00481 unlink(addr_pair->socket_path);
00482 }
00483
00484 #else
00485
00486
00487 close(STDIN_FILENO);
00488 close(STDOUT_FILENO);
00489 #endif
00490
00491 } else {
00492
00493 #ifndef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00494
00495 close(STDIN_FILENO);
00496 close(STDOUT_FILENO);
00497 #endif
00498
00499 }
00500 return rc;
00501 }
00502
00503
00504
00505 static int
00506 netsnmp_ssh_accept(netsnmp_transport *t)
00507 {
00508 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00509
00510
00511
00512 netsnmp_ssh_addr_pair *addr_pair;
00513 int newsock = -1;
00514 struct sockaddr *farend = NULL;
00515 socklen_t farendlen = sizeof(struct sockaddr_un);
00516
00517
00518 if (t != NULL && t->sock >= 0) {
00519 addr_pair = SNMP_MALLOC_TYPEDEF(netsnmp_ssh_addr_pair);
00520
00521 if (addr_pair == NULL) {
00522
00523
00524
00525 DEBUGMSGTL(("ssh", "accept: malloc failed\n"));
00526 return -1;
00527 }
00528
00529 farend = (struct sockaddr *) &addr_pair->unix_socket_end;
00530
00531 newsock = accept(t->sock, farend, &farendlen);
00532
00533
00534 {
00535 int one = 1;
00536 setsockopt(newsock, SOL_SOCKET, SO_PASSCRED, (void *) &one,
00537 sizeof(one));
00538 }
00539
00540 if (newsock < 0) {
00541 DEBUGMSGTL(("ssh","accept failed rc %d errno %d \"%s\"\n",
00542 newsock, errno, strerror(errno)));
00543 free(addr_pair);
00544 return newsock;
00545 }
00546
00547 if (t->data != NULL) {
00548 free(t->data);
00549 }
00550
00551 DEBUGMSGTL(("ssh", "accept succeeded (farend %p len %d)\n",
00552 farend, farendlen));
00553 t->data = addr_pair;
00554 t->data_length = sizeof(netsnmp_ssh_addr_pair);
00555 netsnmp_sock_buffer_set(newsock, SO_SNDBUF, 1, 0);
00556 netsnmp_sock_buffer_set(newsock, SO_RCVBUF, 1, 0);
00557 return newsock;
00558 } else {
00559 return -1;
00560 }
00561
00562 #else
00563
00564
00565
00566 return STDIN_FILENO;
00567 #endif
00568
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 netsnmp_transport *
00580 netsnmp_ssh_transport(struct sockaddr_in *addr, int local)
00581 {
00582 netsnmp_transport *t = NULL;
00583 netsnmp_ssh_addr_pair *addr_pair = NULL;
00584 int rc = 0;
00585 int i, auth_pw = 0;
00586 const char *fingerprint;
00587 char *userauthlist;
00588 struct sockaddr_un *unaddr;
00589 const char *sockpath =
00590 netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00591 NETSNMP_DS_LIB_SSHTOSNMP_SOCKET);
00592 char tmpsockpath[MAXPATHLEN];
00593
00594 if (addr == NULL || addr->sin_family != AF_INET) {
00595 return NULL;
00596 }
00597
00598 t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
00599 if (t == NULL) {
00600 return NULL;
00601 }
00602 memset(t, 0, sizeof(netsnmp_transport));
00603
00604 t->domain = netsnmp_snmpSSHDomain;
00605 t->domain_length =
00606 sizeof(netsnmp_snmpSSHDomain) / sizeof(netsnmp_snmpSSHDomain[0]);
00607
00608 t->flags = NETSNMP_TRANSPORT_FLAG_STREAM | NETSNMP_TRANSPORT_FLAG_TUNNELED;
00609
00610 addr_pair = SNMP_MALLOC_TYPEDEF(netsnmp_ssh_addr_pair);
00611 if (addr_pair == NULL) {
00612 netsnmp_transport_free(t);
00613 return NULL;
00614 }
00615 t->data = addr_pair;
00616 t->data_length = sizeof(netsnmp_ssh_addr_pair);
00617
00618 if (local) {
00619 #ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE
00620
00621
00622
00623
00624 t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;
00625
00626 unaddr = &addr_pair->unix_socket_end;
00627
00628
00629
00630 unaddr->sun_family = AF_UNIX;
00631 if (NULL == sockpath) {
00632 sprintf(tmpsockpath, "%s/%s", get_persistent_directory(),
00633 DEFAULT_SOCK_NAME);
00634 sockpath = tmpsockpath;
00635 }
00636
00637 strcpy(unaddr->sun_path, sockpath);
00638 strcpy(addr_pair->socket_path, sockpath);
00639
00640 t->sock = socket(PF_UNIX, SOCK_STREAM, 0);
00641 if (t->sock < 0) {
00642 netsnmp_transport_free(t);
00643 return NULL;
00644 }
00645
00646
00647 {
00648 int one = 1;
00649 setsockopt(t->sock, SOL_SOCKET, SO_PASSCRED, (void *) &one,
00650 sizeof(one));
00651 }
00652
00653 unlink(unaddr->sun_path);
00654 rc = bind(t->sock, (struct sockaddr *) unaddr, SUN_LEN(unaddr));
00655 if (rc != 0) {
00656 DEBUGMSGTL(("netsnmp_ssh_transport",
00657 "couldn't bind \"%s\", errno %d (%s)\n",
00658 unaddr->sun_path, errno, strerror(errno)));
00659 netsnmp_ssh_close(t);
00660 netsnmp_transport_free(t);
00661 return NULL;
00662 }
00663
00664
00665
00666 {
00667
00668
00669
00670
00671 int sshdomain_sock_perm =
00672 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
00673 NETSNMP_DS_SSHDOMAIN_SOCK_PERM);
00674 int sshdomain_sock_user =
00675 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
00676 NETSNMP_DS_SSHDOMAIN_SOCK_USER);
00677 int sshdomain_sock_group =
00678 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
00679 NETSNMP_DS_SSHDOMAIN_SOCK_GROUP);
00680
00681 DEBUGMSGTL(("ssh", "here: %s, %d, %d, %d\n",
00682 unaddr->sun_path,
00683 sshdomain_sock_perm, sshdomain_sock_user,
00684 sshdomain_sock_group));
00685 if (sshdomain_sock_perm != 0) {
00686 DEBUGMSGTL(("ssh", "Setting socket perms to %d\n",
00687 sshdomain_sock_perm));
00688 chmod(unaddr->sun_path, sshdomain_sock_perm);
00689 }
00690
00691 if (sshdomain_sock_user || sshdomain_sock_group) {
00692
00693
00694
00695
00696 if (sshdomain_sock_user == 0 )
00697 sshdomain_sock_user = -1;
00698 if (sshdomain_sock_group == 0 )
00699 sshdomain_sock_group = -1;
00700 DEBUGMSGTL(("ssh", "Setting socket user/group to %d/%d\n",
00701 sshdomain_sock_user, sshdomain_sock_group));
00702 chown(unaddr->sun_path,
00703 sshdomain_sock_user, sshdomain_sock_group);
00704 }
00705 }
00706
00707 rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
00708 if (rc != 0) {
00709 DEBUGMSGTL(("netsnmp_ssh_transport",
00710 "couldn't listen to \"%s\", errno %d (%s)\n",
00711 unaddr->sun_path, errno, strerror(errno)));
00712 netsnmp_ssh_close(t);
00713 netsnmp_transport_free(t);
00714 return NULL;
00715 }
00716
00717
00718 #else
00719
00720
00721
00722
00723
00724
00725 t->sock = STDIN_FILENO;
00726 #endif
00727
00728 } else {
00729
00730
00731
00732 memcpy(&(addr_pair->remote_addr), addr, sizeof(struct sockaddr_in));
00733
00734 t->sock = socket(PF_INET, SOCK_STREAM, 0);
00735 if (t->sock < 0) {
00736 netsnmp_transport_free(t);
00737 return NULL;
00738 }
00739
00740 t->remote = (u_char *)malloc(6);
00741 if (t->remote == NULL) {
00742 netsnmp_ssh_close(t);
00743 netsnmp_transport_free(t);
00744 return NULL;
00745 }
00746 memcpy(t->remote, (u_char *) & (addr->sin_addr.s_addr), 4);
00747 t->remote[4] = (htons(addr->sin_port) & 0xff00) >> 8;
00748 t->remote[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
00749 t->remote_length = 6;
00750
00751
00752
00753
00754
00755
00756
00757
00758 rc = connect(t->sock, (struct sockaddr *)addr,
00759 sizeof(struct sockaddr));
00760
00761 if (rc < 0) {
00762 netsnmp_ssh_close(t);
00763 netsnmp_transport_free(t);
00764 return NULL;
00765 }
00766
00767
00768
00769
00770
00771
00772 netsnmp_sock_buffer_set(t->sock, SO_SNDBUF, local, 0);
00773 netsnmp_sock_buffer_set(t->sock, SO_RCVBUF, local, 0);
00774
00775
00776 addr_pair->session = libssh2_session_init();
00777 if (libssh2_session_startup(addr_pair->session, t->sock)) {
00778 shutdown:
00779 snmp_log(LOG_ERR, "Failed to establish an SSH session\n");
00780 netsnmp_ssh_close(t);
00781 netsnmp_transport_free(t);
00782 return NULL;
00783 }
00784
00785
00786
00787
00788
00789
00790 fingerprint =
00791 libssh2_hostkey_hash(addr_pair->session, LIBSSH2_HOSTKEY_HASH_MD5);
00792 DEBUGMSGTL(("ssh", "Fingerprint: "));
00793 for(i = 0; i < 16; i++) {
00794 DEBUGMSG(("ssh", "%02x",
00795 (unsigned char)fingerprint[i]));
00796 }
00797 DEBUGMSG(("ssh", "\n"));
00798
00799
00800 userauthlist =
00801 libssh2_userauth_list(addr_pair->session,
00802 username, strlen(username));
00803 DEBUGMSG(("ssh", "Authentication methods: %s\n", userauthlist));
00804
00805
00806
00807 if (strstr(userauthlist, "publickey") != NULL) {
00808 auth_pw |= 4;
00809 }
00810
00811
00812 if (auth_pw & 4) {
00813
00814 if (libssh2_userauth_publickey_fromfile(addr_pair->session,
00815 username,
00816 keyfile1, keyfile2,
00817 NULL)) {
00818 snmp_log(LOG_ERR,"Authentication by public key failed!\n");
00819 goto shutdown;
00820 } else {
00821 DEBUGMSG(("ssh",
00822 "\tAuthentication by public key succeeded.\n"));
00823 }
00824 } else {
00825 snmp_log(LOG_ERR,"Authentication by public key failed!\n");
00826 goto shutdown;
00827 }
00828
00829
00830
00831
00832 if (!(addr_pair->channel =
00833 libssh2_channel_open_session(addr_pair->session))) {
00834 snmp_log(LOG_ERR, "Unable to open a session\n");
00835 goto shutdown;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 if (libssh2_channel_subsystem(addr_pair->channel, "snmp")) {
00847 snmp_log(LOG_ERR, "Failed to request the ssh 'snmp' subsystem\n");
00848 goto shutdown;
00849 }
00850 }
00851
00852 DEBUGMSG(("ssh","Opened connection.\n"));
00853
00854
00855
00856
00857
00858 t->msgMaxSize = 0x7fffffff;
00859 t->f_recv = netsnmp_ssh_recv;
00860 t->f_send = netsnmp_ssh_send;
00861 t->f_close = netsnmp_ssh_close;
00862 t->f_accept = netsnmp_ssh_accept;
00863 t->f_fmtaddr = netsnmp_ssh_fmtaddr;
00864
00865 return t;
00866 }
00867
00868
00869
00870 netsnmp_transport *
00871 netsnmp_ssh_create_tstring(const char *str, int local,
00872 const char *default_target)
00873 {
00874 struct sockaddr_in addr;
00875
00876 if (netsnmp_sockaddr_in2(&addr, str, default_target)) {
00877 return netsnmp_ssh_transport(&addr, local);
00878 } else {
00879 return NULL;
00880 }
00881 }
00882
00883
00884
00885 netsnmp_transport *
00886 netsnmp_ssh_create_ostring(const u_char * o, size_t o_len, int local)
00887 {
00888 struct sockaddr_in addr;
00889
00890 if (o_len == 6) {
00891 unsigned short porttmp = (o[4] << 8) + o[5];
00892 addr.sin_family = AF_INET;
00893 memcpy((u_char *) & (addr.sin_addr.s_addr), o, 4);
00894 addr.sin_port = htons(porttmp);
00895 return netsnmp_ssh_transport(&addr, local);
00896 }
00897 return NULL;
00898 }
00899
00900 void
00901 sshdomain_parse_socket(const char *token, char *cptr)
00902 {
00903 char *socket_perm, *socket_user, *socket_group;
00904 int uid = -1;
00905 int gid = -1;
00906 int s_perm = -1;
00907 char *st;
00908
00909 DEBUGMSGTL(("ssh/config", "parsing socket info: %s\n", cptr));
00910 socket_perm = strtok_r(cptr, " \t", &st);
00911 socket_user = strtok_r(NULL, " \t", &st);
00912 socket_group = strtok_r(NULL, " \t", &st);
00913
00914 if (socket_perm) {
00915 s_perm = strtol(socket_perm, NULL, 8);
00916 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00917 NETSNMP_DS_SSHDOMAIN_SOCK_PERM, s_perm);
00918 DEBUGMSGTL(("ssh/config", "socket permissions: %o (%d)\n",
00919 s_perm, s_perm));
00920 }
00921
00922
00923
00924 if (socket_user) {
00925 uid = netsnmp_str_to_uid(socket_user);
00926 if ( uid != 0 )
00927 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00928 NETSNMP_DS_SSHDOMAIN_SOCK_USER, uid);
00929 DEBUGMSGTL(("ssh/config", "socket owner: %s (%d)\n",
00930 socket_user, uid));
00931 }
00932
00933
00934
00935
00936 if (socket_group) {
00937 gid = netsnmp_str_to_gid(socket_group);
00938 if ( gid != 0 )
00939 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00940 NETSNMP_DS_SSHDOMAIN_SOCK_GROUP, gid);
00941 DEBUGMSGTL(("ssh/config", "socket group: %s (%d)\n",
00942 socket_group, gid));
00943 }
00944 }
00945
00946 void
00947 netsnmp_ssh_ctor(void)
00948 {
00949 sshDomain.name = netsnmp_snmpSSHDomain;
00950 sshDomain.name_length = sizeof(netsnmp_snmpSSHDomain) / sizeof(oid);
00951 sshDomain.prefix = (const char **)calloc(2, sizeof(char *));
00952 sshDomain.prefix[0] = "ssh";
00953
00954 sshDomain.f_create_from_tstring_new = netsnmp_ssh_create_tstring;
00955 sshDomain.f_create_from_ostring = netsnmp_ssh_create_ostring;
00956
00957 register_config_handler("snmp", "sshtosnmpsocketperms",
00958 &sshdomain_parse_socket, NULL,
00959 "socketperms [username [groupname]]");
00960
00961 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "sshtosnmpsocket",
00962 NETSNMP_DS_LIBRARY_ID,
00963 NETSNMP_DS_LIB_SSHTOSNMP_SOCKET);
00964
00965 DEBUGMSGTL(("ssh", "registering the ssh domain\n"));
00966 netsnmp_tdomain_register(&sshDomain);
00967 }
00968
00969