Return to stream_service_unix.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / networking / streams |
1.1 misho 1: /* 2: * Copyright (C) 2013 Martin Willi 3: * Copyright (C) 2013 revosec AG 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include <library.h> 17: #include <networking/streams/stream_unix.h> 18: 19: #include <errno.h> 20: #include <unistd.h> 21: #include <sys/socket.h> 22: #include <sys/un.h> 23: #include <sys/stat.h> 24: 25: /** 26: * See header 27: */ 28: stream_service_t *stream_service_create_unix(char *uri, int backlog) 29: { 30: struct sockaddr_un addr; 31: mode_t old; 32: int fd, len; 33: 34: len = stream_parse_uri_unix(uri, &addr); 35: if (len == -1) 36: { 37: DBG1(DBG_NET, "invalid stream URI: '%s'", uri); 38: return NULL; 39: } 40: if (!lib->caps->check(lib->caps, CAP_CHOWN)) 41: { /* required to chown(2) service socket */ 42: DBG1(DBG_NET, "cannot change ownership of socket '%s' without " 43: "CAP_CHOWN capability. socket directory should be accessible to " 44: "UID/GID under which the daemon will run", uri); 45: } 46: fd = socket(AF_UNIX, SOCK_STREAM, 0); 47: if (fd == -1) 48: { 49: DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno)); 50: return NULL; 51: } 52: unlink(addr.sun_path); 53: 54: old = umask(S_IRWXO); 55: if (bind(fd, (struct sockaddr*)&addr, len) < 0) 56: { 57: DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno)); 58: close(fd); 59: return NULL; 60: } 61: umask(old); 62: /* Only attempt to change owner of socket if we have CAP_CHOWN. Otherwise, 63: * attempt to change group of socket to group under which charon runs after 64: * dropping caps. This requires the user that charon starts as to: 65: * a) Have write access to the socket dir. 66: * b) Belong to the group that charon will run under after dropping caps. */ 67: if (lib->caps->check(lib->caps, CAP_CHOWN)) 68: { 69: if (chown(addr.sun_path, lib->caps->get_uid(lib->caps), 70: lib->caps->get_gid(lib->caps)) != 0) 71: { 72: DBG1(DBG_NET, "changing socket owner/group for '%s' failed: %s", 73: uri, strerror(errno)); 74: } 75: } 76: else 77: { 78: if (chown(addr.sun_path, -1, lib->caps->get_gid(lib->caps)) != 0) 79: { 80: DBG1(DBG_NET, "changing socket group for '%s' failed: %s", 81: uri, strerror(errno)); 82: } 83: } 84: if (listen(fd, backlog) < 0) 85: { 86: DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno)); 87: unlink(addr.sun_path); 88: close(fd); 89: return NULL; 90: } 91: return stream_service_create_from_fd(fd); 92: }