1*b819cea2SGordon Ross /* 2*b819cea2SGordon Ross * This file and its contents are supplied under the terms of the 3*b819cea2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0. 4*b819cea2SGordon Ross * You may only use this file in accordance with the terms of version 5*b819cea2SGordon Ross * 1.0 of the CDDL. 6*b819cea2SGordon Ross * 7*b819cea2SGordon Ross * A full copy of the text of the CDDL should have accompanied this 8*b819cea2SGordon Ross * source. A copy of the CDDL is also available via the Internet at 9*b819cea2SGordon Ross * http://www.illumos.org/license/CDDL. 10*b819cea2SGordon Ross */ 11*b819cea2SGordon Ross 12*b819cea2SGordon Ross /* 13*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 14*b819cea2SGordon Ross */ 15*b819cea2SGordon Ross 16*b819cea2SGordon Ross /* 17*b819cea2SGordon Ross * fork/exec a privileged helper to do the bind. 18*b819cea2SGordon Ross */ 19*b819cea2SGordon Ross 20*b819cea2SGordon Ross #include <stdio.h> 21*b819cea2SGordon Ross #include <string.h> 22*b819cea2SGordon Ross #include <unistd.h> 23*b819cea2SGordon Ross #include <errno.h> 24*b819cea2SGordon Ross #include <sys/types.h> 25*b819cea2SGordon Ross #include <sys/wait.h> 26*b819cea2SGordon Ross #include <sys/socket.h> 27*b819cea2SGordon Ross #include <sys/note.h> 28*b819cea2SGordon Ross #include <netinet/in.h> 29*b819cea2SGordon Ross #include <arpa/inet.h> 30*b819cea2SGordon Ross 31*b819cea2SGordon Ross int 32*b819cea2SGordon Ross ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen) 33*b819cea2SGordon Ross { 34*b819cea2SGordon Ross char familystr[8]; 35*b819cea2SGordon Ross char portstr[12]; 36*b819cea2SGordon Ross char addrstr[INET6_ADDRSTRLEN]; 37*b819cea2SGordon Ross char *argv[6]; 38*b819cea2SGordon Ross const char *p; 39*b819cea2SGordon Ross /* LINTED E_BAD_PTR_CAST_ALIGN */ 40*b819cea2SGordon Ross struct sockaddr_in *sin = (struct sockaddr_in *)addr; 41*b819cea2SGordon Ross /* LINTED E_BAD_PTR_CAST_ALIGN */ 42*b819cea2SGordon Ross struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 43*b819cea2SGordon Ross int pid, err, stat; 44*b819cea2SGordon Ross _NOTE(ARGUNUSED(addrlen)); 45*b819cea2SGordon Ross 46*b819cea2SGordon Ross (void) snprintf(familystr, sizeof (familystr), "%d", addr->sa_family); 47*b819cea2SGordon Ross switch (addr->sa_family) { 48*b819cea2SGordon Ross case AF_INET: 49*b819cea2SGordon Ross (void) snprintf(portstr, sizeof (portstr), "%d", 50*b819cea2SGordon Ross ntohs(sin->sin_port)); 51*b819cea2SGordon Ross p = inet_ntop(AF_INET, &sin->sin_addr, 52*b819cea2SGordon Ross addrstr, sizeof (addrstr)); 53*b819cea2SGordon Ross break; 54*b819cea2SGordon Ross case AF_INET6: 55*b819cea2SGordon Ross (void) snprintf(portstr, sizeof (portstr), "%d", 56*b819cea2SGordon Ross ntohs(sin6->sin6_port)); 57*b819cea2SGordon Ross p = inet_ntop(AF_INET6, &sin6->sin6_addr, 58*b819cea2SGordon Ross addrstr, sizeof (addrstr)); 59*b819cea2SGordon Ross break; 60*b819cea2SGordon Ross default: 61*b819cea2SGordon Ross p = NULL; 62*b819cea2SGordon Ross break; 63*b819cea2SGordon Ross } 64*b819cea2SGordon Ross if (p == NULL) { 65*b819cea2SGordon Ross err = errno; 66*b819cea2SGordon Ross (void) fprintf(stdout, "ksocket_bind_helper, inet_ntop %s\n", 67*b819cea2SGordon Ross strerror(err)); 68*b819cea2SGordon Ross return (err); 69*b819cea2SGordon Ross } 70*b819cea2SGordon Ross 71*b819cea2SGordon Ross (void) fprintf(stdout, "ksocket_bind_helper, " 72*b819cea2SGordon Ross "family=%s addr=%s port=%s\n", 73*b819cea2SGordon Ross familystr, addrstr, portstr); 74*b819cea2SGordon Ross 75*b819cea2SGordon Ross argv[0] = "/usr/bin/pfexec"; 76*b819cea2SGordon Ross argv[1] = "/usr/lib/smbsrv/bind-helper"; 77*b819cea2SGordon Ross argv[2] = familystr; 78*b819cea2SGordon Ross argv[3] = addrstr; 79*b819cea2SGordon Ross argv[4] = portstr; 80*b819cea2SGordon Ross argv[5] = NULL; 81*b819cea2SGordon Ross 82*b819cea2SGordon Ross pid = vfork(); 83*b819cea2SGordon Ross if (pid == -1) { 84*b819cea2SGordon Ross err = errno; 85*b819cea2SGordon Ross perror("fork"); 86*b819cea2SGordon Ross return (err); 87*b819cea2SGordon Ross } 88*b819cea2SGordon Ross if (pid == 0) { 89*b819cea2SGordon Ross (void) dup2(fd, 0); 90*b819cea2SGordon Ross (void) execv(argv[0], argv); 91*b819cea2SGordon Ross err = errno; 92*b819cea2SGordon Ross perror("execv"); 93*b819cea2SGordon Ross return (err); 94*b819cea2SGordon Ross } 95*b819cea2SGordon Ross err = waitpid(pid, &stat, 0); 96*b819cea2SGordon Ross if (err == -1) { 97*b819cea2SGordon Ross err = errno; 98*b819cea2SGordon Ross perror("waitpid"); 99*b819cea2SGordon Ross return (err); 100*b819cea2SGordon Ross } 101*b819cea2SGordon Ross if (WIFEXITED(stat)) { 102*b819cea2SGordon Ross err = WEXITSTATUS(stat); 103*b819cea2SGordon Ross if (err == 0) 104*b819cea2SGordon Ross return (0); 105*b819cea2SGordon Ross (void) fprintf(stderr, "helper exit %d\n", err); 106*b819cea2SGordon Ross } 107*b819cea2SGordon Ross return (EACCES); 108*b819cea2SGordon Ross } 109