common.c revision fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * System Security Services Daemon. NSS client interface
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Copyright (C) Simo Sorce 2007
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * Winbind derived code:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Copyright (C) Tim Potter 2000
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Copyright (C) Andrew Tridgell 2000
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Copyright (C) Andrew Bartlett 2002
45db68ae27147955a4be4c2c772041824c0dc00fStephen Gallagher * This program is free software; you can redistribute it and/or modify
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher * it under the terms of the GNU Lesser General Public License as
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * published by the Free Software Foundation; either version 2.1 of the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * License, or (at your option) any later version.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * This program is distributed in the hope that it will be useful,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * but WITHOUT ANY WARRANTY; without even the implied warranty of
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * GNU Lesser General Public License for more details.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * You should have received a copy of the GNU Lesser General Public
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * License along with this program; if not, write to the Free Software
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* common functions */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherint sss_cli_sd = -1; /* the sss client socket descriptor */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 0-3: 32bit unsigned with length (the complete packet length: 0 to X)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 4-7: 32bit unsigned with command code
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 8-11: 32bit unsigned (reserved)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 12-15: 32bit unsigned (reserved)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * byte 16-X: (optional) request structure associated to the command code used
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagherstatic enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[0] = SSS_NSS_HEADER_SIZE + (rd?rd->len:0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Write failed */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher * byte 0-3: 32bit unsigned with length (the complete packet length: 0 to X)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher * byte 4-7: 32bit unsigned with command code
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 8-11: 32bit unsigned with the request status (server errno)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * byte 12-15: 32bit unsigned (reserved)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * byte 16-X: (optional) reply structure associated to the command code used
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[0] = SSS_NSS_HEADER_SIZE; /* unitl we know the real lenght */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Read failed. I think the only useful thing
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * we can do here is just return -1 and fail
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * since the transaction has failed half way
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (datarecv == SSS_NSS_HEADER_SIZE && *len == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* at this point recv buf is not yet
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * allocated and the header has just
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * been read, do checks and proceed */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* server side error */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* wrong command id */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* this function will check command codes match and returned length is ok */
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher/* repbuf and replen report only the data section not the header */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic enum nss_status sss_nss_make_request_nochecks(
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* send data */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* data sent, now get reply */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_nss_recv_rep(cmd, &buf, &len, errnop);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* we got through, now we have the custom data in buf if any,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * return it if requested */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* GET_VERSION Reply:
056302a92862fda16351d7192600746746f38e5dStephen Gallagher * 0-3: 32bit unsigned version number
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher nret = sss_nss_make_request_nochecks(SSS_GET_VERSION, NULL,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (((uint32_t *)repbuf)[0] == SSS_PROTOCOL_VERSION) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* this 2 functions are adapted from samba3 winbinbd's wb_common.c */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher/* Make sure socket handle isn't stdin (0), stdout(1) or stderr(2) by setting
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the limit to 3 */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int make_nonstd_fd_internals(int fd, int limit)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Paranoia */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* use the program stack to hold our list of FDs to close */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/****************************************************************************
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if SYSV use O_NDELAY
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if BSD use FNDELAY
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher Set close on exec also.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher****************************************************************************/
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* Socket should be nonblocking. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#else /* BSD */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (fcntl(new_fd, F_SETFL, flags) == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Socket should be closed on exec() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher result = flags = fcntl(new_fd, F_GETFD, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int sss_nss_open_socket(int *errnop, const char *socket_name)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher memset(&nssaddr, 0, sizeof(struct sockaddr_un));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* set as non-blocking, close on exec, and make sure standard
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * descriptors are not used */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* this piece is adapted from winbind client code */
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher ret = connect(sd, (struct sockaddr *)&nssaddr,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher tv.tv_sec = SSS_CLI_SOCKET_TIMEOUT - wait_time;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = select(sd + 1, NULL, &w_fds, NULL, &tv);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = getsockopt(sd, SOL_SOCKET, SO_ERROR,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (wait_time >= SSS_CLI_SOCKET_TIMEOUT) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if we get here connect() failed or we timed out */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic enum sss_status sss_cli_check_socket(int *errnop, const char *socket_name)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* check if the socket has been closed on the other side */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!(pfd.revents & (POLLIN | POLLOUT))) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher mysd = sss_nss_open_socket(errnop, socket_name);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher/* this function will check command codes match and returned length is ok */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher/* repbuf and replen report only the data section not the header */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherenum nss_status sss_nss_make_request(enum sss_cli_command cmd,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* avoid looping in the nss daemon */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (envval && strcmp(envval, "NO") == 0) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return sss_nss_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint sss_pam_make_request(enum sss_cli_command cmd,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* avoid looping in the pam daemon */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (envval && strcmp(envval, "NO") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_cli_check_socket(errnop, SSS_PAM_SOCKET_NAME);