LCOV - code coverage report
Current view: top level - src - assuan-socket-server.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 70 0.0 %
Date: 2016-12-01 18:29:29 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /* assuan-socket-server.c - Assuan socket based server
       2             :    Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc.
       3             : 
       4             :    This file is part of Assuan.
       5             : 
       6             :    Assuan is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    Assuan is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #ifdef HAVE_CONFIG_H
      21             : #include <config.h>
      22             : #endif
      23             : 
      24             : #include <stdlib.h>
      25             : #include <stdio.h>
      26             : #include <errno.h>
      27             : #ifdef HAVE_UNISTD_H
      28             : # include <unistd.h>
      29             : #endif
      30             : #ifdef HAVE_SYS_TYPES_H
      31             : # include <sys/types.h>
      32             : #endif
      33             : #ifdef HAVE_UCRED_H
      34             : #include <ucred.h>
      35             : #endif
      36             : #ifdef HAVE_W32_SYSTEM
      37             : # ifdef HAVE_WINSOCK2_H
      38             : #  include <winsock2.h>
      39             : # endif 
      40             : # include <windows.h>
      41             : # if HAVE_SYS_SOCKET_H
      42             : #  include <sys/socket.h>
      43             : # elif HAVE_WS2TCPIP_H
      44             : #  include <ws2tcpip.h>
      45             : # endif
      46             : #else
      47             : # include <sys/socket.h>
      48             : # include <sys/un.h>
      49             : #endif
      50             : 
      51             : #include "debug.h"
      52             : #include "assuan-defs.h"
      53             : 
      54             : static gpg_error_t
      55           0 : accept_connection_bottom (assuan_context_t ctx)
      56             : {
      57           0 :   assuan_fd_t fd = ctx->connected_fd;
      58             : 
      59           0 :   TRACE (ctx, ASSUAN_LOG_SYSIO, "accept_connection_bottom", ctx);
      60             : 
      61           0 :   ctx->peercred_valid = 0;
      62             : #ifdef HAVE_SO_PEERCRED
      63             :   {
      64             :     struct ucred cr;
      65           0 :     socklen_t cl = sizeof cr;
      66             : 
      67           0 :     if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
      68             :       {
      69           0 :          ctx->peercred.pid = cr.pid;
      70           0 :          ctx->peercred.uid = cr.uid;
      71           0 :          ctx->peercred.gid = cr.gid;
      72           0 :          ctx->peercred_valid = 1;
      73             : 
      74             :          /* This overrides any already set PID if the function returns
      75             :             a valid one. */
      76           0 :          if (cr.pid != ASSUAN_INVALID_PID && cr.pid)
      77           0 :            ctx->pid = cr.pid;
      78             :       }
      79             :   }
      80             : #elif defined (HAVE_GETPEERUCRED)
      81             :   {
      82             :     ucred_t *ucred = NULL;
      83             : 
      84             :     if (getpeerucred (fd, &ucred) != -1)
      85             :       {
      86             :         ctx->peercred.uid = ucred_geteuid (ucred);
      87             :         ctx->peercred.gid = ucred_getegid (ucred);
      88             :         ctx->peercred.pid = ucred_getpid (ucred);
      89             :         ctx->peercred_valid = 1;
      90             :         ucred_free (ucred);
      91             :       }
      92             :   }
      93             : #elif defined (HAVE_LOCAL_PEEREID)
      94             :   {
      95             :     struct unpcbid unp;
      96             :     socklen_t unpl = sizeof unp;
      97             : 
      98             :     if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
      99             :       {
     100             :         ctx->peercred.pid = unp.unp_pid;
     101             :         ctx->peercred.uid = unp.unp_euid;
     102             :         ctx->peercred.gid = unp.unp_egid;
     103             :         ctx->peercred_valid = 1;
     104             :       }
     105             :   }
     106             : #elif defined(HAVE_GETPEEREID)
     107             :   {
     108             :     if (getpeereid (fd, &ctx->peercred.uid, &ctx->peercred.gid) != -1)
     109             :       {
     110             :         ctx->peercred.pid = ASSUAN_INVALID_PID;
     111             :         ctx->peercred_valid = 1;
     112             :       }
     113             :   }
     114             : #endif
     115             : 
     116           0 :   ctx->inbound.fd = fd;
     117           0 :   ctx->inbound.eof = 0;
     118           0 :   ctx->inbound.linelen = 0;
     119           0 :   ctx->inbound.attic.linelen = 0;
     120           0 :   ctx->inbound.attic.pending = 0;
     121             : 
     122           0 :   ctx->outbound.fd = fd;
     123           0 :   ctx->outbound.data.linelen = 0;
     124           0 :   ctx->outbound.data.error = 0;
     125             :   
     126           0 :   ctx->flags.confidential = 0;
     127             : 
     128           0 :   return 0;
     129             : }
     130             : 
     131             : 
     132             : static gpg_error_t
     133           0 : accept_connection (assuan_context_t ctx)
     134             : {
     135             :   assuan_fd_t fd;
     136             :   struct sockaddr_un clnt_addr;
     137           0 :   socklen_t len = sizeof clnt_addr;
     138             : 
     139           0 :   TRACE1 (ctx, ASSUAN_LOG_SYSIO, "accept_connection", ctx, 
     140             :          "listen_fd=0x%x", ctx->listen_fd);
     141             : 
     142           0 :   fd = SOCKET2HANDLE(accept (HANDLE2SOCKET(ctx->listen_fd), 
     143             :                              (struct sockaddr*)&clnt_addr, &len ));
     144           0 :   if (fd == ASSUAN_INVALID_FD)
     145             :     {
     146           0 :       return _assuan_error (ctx, gpg_err_code_from_syserror ());
     147             :     }
     148           0 :   TRACE1 (ctx, ASSUAN_LOG_SYSIO, "accept_connection", ctx, 
     149             :           "fd->0x%x", fd);
     150           0 :   if (_assuan_sock_check_nonce (ctx, fd, &ctx->listen_nonce))
     151             :     {
     152           0 :       _assuan_close (ctx, fd);
     153           0 :       return _assuan_error (ctx, GPG_ERR_ASS_ACCEPT_FAILED);
     154             :     }
     155             : 
     156           0 :   ctx->connected_fd = fd;
     157           0 :   return accept_connection_bottom (ctx);
     158             : }
     159             : 
     160             : 
     161             : /* 
     162             :    Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
     163             :               1 - FD has already been accepted.
     164             : */
     165             : gpg_error_t
     166           0 : assuan_init_socket_server (assuan_context_t ctx, assuan_fd_t fd,
     167             :                            unsigned int flags)
     168             : {
     169             :   gpg_error_t rc;
     170           0 :   TRACE_BEG2 (ctx, ASSUAN_LOG_CTX, "assuan_init_socket_server", ctx,
     171             :               "fd=0x%x, flags=0x%x", fd, flags);
     172             :   
     173           0 :   rc = _assuan_register_std_commands (ctx);
     174           0 :   if (rc)
     175           0 :     return TRACE_ERR (rc);
     176             : 
     177           0 :   ctx->engine.release = _assuan_server_release;
     178           0 :   ctx->engine.readfnc = _assuan_simple_read;
     179           0 :   ctx->engine.writefnc = _assuan_simple_write;
     180           0 :   ctx->engine.sendfd = NULL;
     181           0 :   ctx->engine.receivefd = NULL;
     182           0 :   ctx->is_server = 1;
     183           0 :   if (flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
     184             :     /* We want a second accept to indicate EOF. */
     185           0 :     ctx->max_accepts = 1;
     186             :   else
     187           0 :     ctx->max_accepts = -1;
     188           0 :   ctx->input_fd = ASSUAN_INVALID_FD;
     189           0 :   ctx->output_fd = ASSUAN_INVALID_FD;
     190             : 
     191           0 :   ctx->inbound.fd = ASSUAN_INVALID_FD;
     192           0 :   ctx->outbound.fd = ASSUAN_INVALID_FD;
     193             : 
     194           0 :   if (flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
     195             :     {
     196           0 :       ctx->listen_fd = ASSUAN_INVALID_FD;
     197           0 :       ctx->connected_fd = fd;
     198             :     }
     199             :   else
     200             :     {
     201           0 :       ctx->listen_fd = fd;
     202           0 :       ctx->connected_fd = ASSUAN_INVALID_FD;
     203             :     }
     204           0 :   ctx->accept_handler = ((flags & ASSUAN_SOCKET_SERVER_ACCEPTED)
     205             :                          ? accept_connection_bottom 
     206           0 :                          : accept_connection);
     207           0 :   ctx->finish_handler = _assuan_server_finish;
     208             : 
     209           0 :   if (flags & ASSUAN_SOCKET_SERVER_FDPASSING)
     210           0 :     _assuan_init_uds_io (ctx);
     211             : 
     212           0 :   rc = _assuan_register_std_commands (ctx);
     213           0 :   if (rc)
     214           0 :     _assuan_reset (ctx);
     215           0 :   return TRACE_ERR (rc);
     216             : }
     217             : 
     218             : 
     219             : /* Save a copy of NONCE in context CTX.  This should be used to
     220             :    register the server's nonce with an context established by
     221             :    assuan_init_socket_server.  */
     222             : void
     223           0 : assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce)
     224             : {
     225           0 :   if (ctx && nonce)
     226           0 :     ctx->listen_nonce = *nonce;
     227           0 : }

Generated by: LCOV version 1.11