~ubuntu-branches/ubuntu/natty/postfix/natty-security

« back to all changes in this revision

Viewing changes to src/util/upass_connect.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2011-02-22 05:26:41 UTC
  • mfrom: (1.1.27 upstream)
  • Revision ID: james.westby@ubuntu.com-20110222052641-l05d2bsz2kka0yca
Tags: 2.8.0-1~build1
natty version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*++
2
 
/* NAME
3
 
/*      upass_connect 3
4
 
/* SUMMARY
5
 
/*      connect to UNIX-domain file descriptor listener
6
 
/* SYNOPSIS
7
 
/*      #include <connect.h>
8
 
/*
9
 
/*      int     upass_connect(addr, block_mode, timeout)
10
 
/*      const char *addr;
11
 
/*      int     block_mode;
12
 
/*      int     timeout;
13
 
/* DESCRIPTION
14
 
/*      upass_connect() connects to a file descriptor listener in
15
 
/*      the UNIX domain at the specified address, sends one half
16
 
/*      of a socketpair to the listener, and returns the other half
17
 
/*      to the caller.
18
 
/*
19
 
/*      The file descriptor transporting connection is closed by
20
 
/*      a background thread. Some kernels might otherwise discard
21
 
/*      the descriptor before the server has received it.
22
 
/*
23
 
/*      Arguments:
24
 
/* .IP addr
25
 
/*      Null-terminated string with connection destination.
26
 
/* .IP block_mode
27
 
/*      Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
28
 
/*      blocking mode. This setting has no effect on the connection
29
 
/*      establishment process.
30
 
/* .IP timeout
31
 
/*      Bounds the number of seconds that the operation may take. Specify
32
 
/*      a value <= 0 to disable the time limit.
33
 
/* DIAGNOSTICS
34
 
/*      The result is -1 in case the connection could not be made.
35
 
/*      Fatal errors: other system call failures.
36
 
/* LICENSE
37
 
/* .ad
38
 
/* .fi
39
 
/*      The Secure Mailer license must be distributed with this software.
40
 
/* AUTHOR(S)
41
 
/*      Wietse Venema
42
 
/*      IBM T.J. Watson Research
43
 
/*      P.O. Box 704
44
 
/*      Yorktown Heights, NY 10598, USA
45
 
/*--*/
46
 
 
47
 
/* System interfaces. */
48
 
 
49
 
#include <sys_defs.h>
50
 
#include <sys/socket.h>
51
 
#include <sys/un.h>
52
 
#include <string.h>
53
 
#include <unistd.h>
54
 
#include <errno.h>
55
 
 
56
 
/* Utility library. */
57
 
 
58
 
#include <msg.h>
59
 
#include <iostuff.h>
60
 
#include <sane_connect.h>
61
 
#include <connect.h>
62
 
#include <timed_connect.h>
63
 
#include <events.h>
64
 
#include <mymalloc.h>
65
 
#include <sane_socketpair.h>
66
 
 
67
 
 /*
68
 
  * Workaround for hostile kernels that don't support graceful shutdown.
69
 
  */
70
 
struct upass_connect {
71
 
    int     fd;
72
 
    char   *service;
73
 
};
74
 
 
75
 
/* upass_connect_event - disconnect from peer */
76
 
 
77
 
static void upass_connect_event(int event, char *context)
78
 
{
79
 
    struct upass_connect *up = (struct upass_connect *) context;
80
 
    static const char *myname = "upass_connect_event";
81
 
 
82
 
    /*
83
 
     * Disconnect.
84
 
     */
85
 
    if (event == EVENT_TIME)
86
 
        msg_warn("%s: read timeout for service %s", myname, up->service);
87
 
    event_disable_readwrite(up->fd);
88
 
    event_cancel_timer(upass_connect_event, context);
89
 
    if (close(up->fd) < 0)
90
 
        msg_warn("%s: close %s: %m", myname, up->service);
91
 
    myfree(up->service);
92
 
    myfree((char *) up);
93
 
}
94
 
 
95
 
/* upass_connect - connect to UNIX-domain file descriptor listener */
96
 
 
97
 
int     upass_connect(const char *addr, int block_mode, int timeout)
98
 
{
99
 
    struct upass_connect *up;
100
 
    int     pair[2];
101
 
    int     sock;
102
 
 
103
 
    /*
104
 
     * Connect.
105
 
     */
106
 
    if ((sock = unix_connect(addr, BLOCKING, timeout)) < 0)
107
 
        return (-1);
108
 
 
109
 
    /*
110
 
     * Send one socket pair half to the server.
111
 
     */
112
 
#define OUR_HALF        0
113
 
#define THEIR_HALF      1
114
 
 
115
 
    if (sane_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
116
 
        close(sock);
117
 
        return (-1);
118
 
    }
119
 
    if (unix_send_fd(sock, pair[THEIR_HALF]) < 0) {
120
 
        close(pair[THEIR_HALF]);
121
 
        close(pair[OUR_HALF]);
122
 
        close(sock);
123
 
        return (-1);
124
 
    }
125
 
    close(pair[THEIR_HALF]);
126
 
 
127
 
    /*
128
 
     * Return the other socket pair half to the caller. Don't close the
129
 
     * control socket just yet, but wait until the receiver closes it first.
130
 
     * Otherwise, some hostile kernel might discard the socket that we just
131
 
     * sent.
132
 
     */
133
 
    up = (struct upass_connect *) mymalloc(sizeof(*up));
134
 
    up->fd = sock;
135
 
    up->service = mystrdup(addr);
136
 
    if (timeout > 0)
137
 
        event_request_timer(upass_connect_event, (char *) up, timeout + 100);
138
 
    event_enable_read(sock, upass_connect_event, (char *) up);
139
 
    non_blocking(pair[OUR_HALF], block_mode);
140
 
    return (pair[OUR_HALF]);
141
 
}