common.c revision fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/*
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * System Security Services Daemon. NSS client interface
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Copyright (C) Simo Sorce 2007
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *
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
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *
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 *
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 *
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 */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher#include <nss.h>
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher#include <security/pam_modules.h>
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher#include <errno.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <sys/types.h>
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include <sys/socket.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <sys/un.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <unistd.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <stdlib.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <stdint.h>
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include <string.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <fcntl.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include <poll.h>
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "sss_cli.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* common functions */
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagherint sss_cli_sd = -1; /* the sss client socket descriptor */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagherstatic void sss_cli_close_socket(void)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sss_cli_sd != -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(sss_cli_sd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_sd = -1;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Requests:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *
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 Gallagher */
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagherstatic enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sss_cli_req_data *rd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int *errnop)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t header[4];
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t datasent;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[0] = SSS_NSS_HEADER_SIZE + (rd?rd->len:0);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher header[1] = cmd;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher header[2] = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[3] = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher datasent = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while (datasent < header[0]) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct pollfd pfd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int rdsent;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *errnop = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher pfd.fd = sss_cli_sd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pfd.events = POLLOUT;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (res) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case -1:
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher *errnop = errno;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case 0:
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *errnop = ETIME;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case 1:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EPIPE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!(pfd.revents & POLLOUT)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBUSY;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBADF;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (*errnop) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (datasent < SSS_NSS_HEADER_SIZE) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher res = write(sss_cli_sd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (char *)header + datasent,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher SSS_NSS_HEADER_SIZE - datasent);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rdsent = datasent - SSS_NSS_HEADER_SIZE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = write(sss_cli_sd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (const char *)rd->data + rdsent,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rd->len - rdsent);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((res == -1) || (res == 0)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Write failed */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = errno;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher datasent += res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return NSS_STATUS_SUCCESS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher/* Replies:
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher *
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 Gallagher */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint8_t **buf, int *len,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int *errnop)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint32_t header[4];
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t datarecv;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[0] = SSS_NSS_HEADER_SIZE; /* unitl we know the real lenght */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[1] = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[2] = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher header[3] = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher datarecv = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *buf = NULL;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *len = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher while (datarecv < header[0]) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher struct pollfd pfd;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher int bufrecv;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher int res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pfd.fd = sss_cli_sd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pfd.events = POLLIN;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (res) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case -1:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = errno;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher case 0:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = ETIME;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case 1:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EPIPE;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!(pfd.revents & POLLIN)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBUSY;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *errnop = EBADF;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (*errnop) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (datarecv < SSS_NSS_HEADER_SIZE) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = read(sss_cli_sd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (char *)header + datarecv,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher SSS_NSS_HEADER_SIZE - datarecv);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher bufrecv = datarecv - SSS_NSS_HEADER_SIZE;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = read(sss_cli_sd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (char *)(*buf) + bufrecv,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher header[0] - datarecv);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if ((res == -1) || (res == 0)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 * through. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = errno;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher datarecv += res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 */
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (header[2] != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* server side error */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = header[2];
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (*errnop == EAGAIN) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_TRYAGAIN;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (header[1] != cmd) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* wrong command id */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBADMSG;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (header[0] > SSS_NSS_HEADER_SIZE) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *len = header[0] - SSS_NSS_HEADER_SIZE;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher *buf = malloc(*len);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!*buf) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = ENOMEM;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_SUCCESS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sss_cli_req_data *rd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint8_t **repbuf, size_t *replen,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher int *errnop)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher enum nss_status ret;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher uint8_t *buf = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int len = 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* send data */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_nss_send_req(cmd, rd, errnop);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret != NSS_STATUS_SUCCESS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* data sent, now get reply */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_nss_recv_rep(cmd, &buf, &len, errnop);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret != NSS_STATUS_SUCCESS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* we got through, now we have the custom data in buf if any,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher * return it if requested */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (repbuf && buf) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *repbuf = buf;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (replen) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *replen = len;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher free(buf);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (replen) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *replen = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return NSS_STATUS_SUCCESS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* GET_VERSION Reply:
056302a92862fda16351d7192600746746f38e5dStephen Gallagher * 0-3: 32bit unsigned version number
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic int sss_nss_check_version(void)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher uint8_t *repbuf;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher size_t replen;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher enum nss_status nret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int errnop;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher int res = NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher nret = sss_nss_make_request_nochecks(SSS_GET_VERSION, NULL,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher &repbuf, &replen, &errnop);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (nret != NSS_STATUS_SUCCESS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return nret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (!repbuf) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (((uint32_t *)repbuf)[0] == SSS_PROTOCOL_VERSION) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = NSS_STATUS_SUCCESS;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher free(repbuf);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* this 2 functions are adapted from samba3 winbinbd's wb_common.c */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher/* Make sure socket handle isn't stdin (0), stdout(1) or stderr(2) by setting
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the limit to 3 */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define RECURSION_LIMIT 3
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int make_nonstd_fd_internals(int fd, int limit)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int new_fd;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (fd >= 0 && fd <= 2) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#ifdef F_DUPFD
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Paranoia */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (new_fd < 3) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(new_fd);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(fd);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return new_fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#else
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (limit <= 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher new_fd = dup(fd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (new_fd == -1)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
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 close(fd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return new_fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/****************************************************************************
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher else
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if SYSV use O_NDELAY
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if BSD use FNDELAY
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher Set close on exec also.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher****************************************************************************/
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int make_safe_fd(int fd)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int result, flags;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (new_fd == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(fd);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* Socket should be nonblocking. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef O_NONBLOCK
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define FLAG_TO_SET O_NONBLOCK
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#else
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef SYSV
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define FLAG_TO_SET O_NDELAY
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#else /* BSD */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define FLAG_TO_SET FNDELAY
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(new_fd);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher flags |= FLAG_TO_SET;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (fcntl(new_fd, F_SETFL, flags) == -1) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher close(new_fd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#undef FLAG_TO_SET
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Socket should be closed on exec() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef FD_CLOEXEC
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher result = flags = fcntl(new_fd, F_GETFD, 0);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (flags >= 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher flags |= FD_CLOEXEC;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher result = fcntl( new_fd, F_SETFD, flags );
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (result < 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher close(new_fd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return new_fd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int sss_nss_open_socket(int *errnop, const char *socket_name)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sockaddr_un nssaddr;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher int inprogress = 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int wait_time, sleep_time;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int sd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher memset(&nssaddr, 0, sizeof(struct sockaddr_un));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher nssaddr.sun_family = AF_UNIX;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher strncpy(nssaddr.sun_path, socket_name,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher strlen(socket_name) + 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher sd = socket(AF_UNIX, SOCK_STREAM, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sd == -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = errno;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* set as non-blocking, close on exec, and make sure standard
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * descriptors are not used */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sd = make_safe_fd(sd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (sd == -1) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher *errnop = errno;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* this piece is adapted from winbind client code */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher wait_time = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sleep_time = 0;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher while(inprogress) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int connect_errno = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher socklen_t errnosize;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct timeval tv;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fd_set w_fds;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher wait_time += sleep_time;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher ret = connect(sd, (struct sockaddr *)&nssaddr,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher sizeof(nssaddr));
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (ret == 0) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return sd;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher switch(errno) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher case EINPROGRESS:
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher FD_ZERO(&w_fds);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher FD_SET(sd, &w_fds);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher tv.tv_sec = SSS_CLI_SOCKET_TIMEOUT - wait_time;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher tv.tv_usec = 0;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = select(sd + 1, NULL, &w_fds, NULL, &tv);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (ret > 0) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher errnosize = sizeof(connect_errno);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = getsockopt(sd, SOL_SOCKET, SO_ERROR,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher &connect_errno, &errnosize);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret >= 0 && connect_errno == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return sd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher wait_time += SSS_CLI_SOCKET_TIMEOUT;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case EAGAIN:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (wait_time < SSS_CLI_SOCKET_TIMEOUT) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sleep_time = rand() % 2 + 1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sleep(sleep_time);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = errno;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher inprogress = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (wait_time >= SSS_CLI_SOCKET_TIMEOUT) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher inprogress = 0;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if we get here connect() failed or we timed out */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher close(sd);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return -1;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic enum sss_status sss_cli_check_socket(int *errnop, const char *socket_name)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher static pid_t mypid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int mysd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (getpid() != mypid) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher sss_cli_close_socket();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mypid = getpid();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* check if the socket has been closed on the other side */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (sss_cli_sd != -1) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct pollfd pfd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int res;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = 0;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher pfd.fd = sss_cli_sd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pfd.events = POLLIN | POLLOUT;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher res = poll(&pfd, 1, SSS_CLI_SOCKET_TIMEOUT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher switch (res) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher case -1:
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher *errnop = errno;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case 0:
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = ETIME;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case 1:
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EPIPE;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!(pfd.revents & (POLLIN | POLLOUT))) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBUSY;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher default: /* more than one avail ?? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher *errnop = EBADF;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (*errnop) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher sss_cli_close_socket();
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return SSS_STATUS_UNAVAIL;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher return SSS_STATUS_SUCCESS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher mysd = sss_nss_open_socket(errnop, socket_name);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (mysd == -1) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return SSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher sss_cli_sd = mysd;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (sss_nss_check_version()) {
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return SSS_STATUS_SUCCESS;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher }
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher sss_cli_close_socket();
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher *errnop = EFAULT;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return SSS_STATUS_UNAVAIL;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher}
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
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,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher struct sss_cli_req_data *rd,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher uint8_t **repbuf, size_t *replen,
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher int *errnop)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher{
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher enum nss_status ret;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher char *envval;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* avoid looping in the nss daemon */
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher envval = getenv("_SSS_LOOPS");
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (envval && strcmp(envval, "NO") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_NOTFOUND;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher if (ret != SSS_STATUS_SUCCESS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return NSS_STATUS_UNAVAIL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher return sss_nss_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherint sss_pam_make_request(enum sss_cli_command cmd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sss_cli_req_data *rd,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher uint8_t **repbuf, size_t *replen,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int *errnop)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher int ret;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher char *envval;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher /* avoid looping in the pam daemon */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher envval = getenv("_SSS_LOOPS");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (envval && strcmp(envval, "NO") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return PAM_SERVICE_ERR;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_cli_check_socket(errnop, SSS_PAM_SOCKET_NAME);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret != NSS_STATUS_SUCCESS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return PAM_SERVICE_ERR;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return sss_nss_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher