varnish-cache/vmod/vmod_unix_cred_compat.h
0
/*-
1
 * Copyright 2018 UPLEX - Nils Goroll Systemoptimierung
2
 * All rights reserved.
3
 *
4
 * Authors: Geoffrey Simmons <geoffrey.simmons@uplex.de>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 * 1. Redistributions of source code must retain the above copyright notice,
11
 *    this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *    this list of conditions and the following disclaimer in the documentation
14
 *    and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
20
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 *
27
 */
28
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
32
#if defined(HAVE_GETPEEREID)
33
#include <unistd.h>
34
#endif
35
36
#if defined(HAVE_GETPEERUCRED)
37
#include <ucred.h>
38
# if defined(HAVE_SETPPRIV)
39
# include <priv.h>
40
static priv_set_t *priv_proc_info = NULL;
41
# endif
42
#endif
43
44
#define CREDS_FAIL -1
45
#define NOT_SUPPORTED -2
46
47
#if defined(HAVE_GETPEERUCRED) && defined(HAVE_SETPPRIV)
48
static void __attribute__((constructor))
49
cred_compat_init(void)
50
{
51
        AZ(priv_proc_info);
52
        priv_proc_info = priv_allocset();
53
        AN(priv_proc_info);
54
        AZ(priv_addset(priv_proc_info, PRIV_PROC_INFO));
55
}
56
57
static void __attribute__((destructor))
58
cred_compat_fini(void)
59
{
60
        if (priv_proc_info == NULL)
61
                return;
62
        priv_freeset(priv_proc_info);
63
        priv_proc_info = NULL;
64
}
65
#endif
66
67
static int
68 200
get_ids(int fd, uid_t *uid, gid_t *gid)
69
{
70
71
#if defined(SO_PEERCRED)
72
#if defined(__OpenBSD__)
73
        typedef struct sockpeercred ucred_t;
74
#else
75
        typedef struct ucred ucred_t;
76
#endif
77
78
        ucred_t ucred;
79
        socklen_t l = sizeof(ucred);
80
81
        errno = 0;
82
        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *) &ucred, &l) != 0)
83
                return (CREDS_FAIL);
84
        *uid = ucred.uid;
85
        *gid = ucred.gid;
86
        return (0);
87
88
#elif defined(HAVE_GETPEEREID)
89
90 200
        errno = 0;
91 200
        if (getpeereid(fd, uid, gid) != 0)
92 0
                return (CREDS_FAIL);
93 200
        return (0);
94
95
#elif defined(HAVE_GETPEERUCRED)
96
        char buf[ucred_size()];
97
        ucred_t *ucredp = (ucred_t *)buf;
98
99
# if defined(HAVE_SETPPRIV)
100
        priv_set_t *priv = NULL;
101
102
        errno = 0;
103
        if (!priv_ineffect(PRIV_PROC_INFO)) {
104
                priv = priv_proc_info;
105
                if (setppriv(PRIV_ON, PRIV_EFFECTIVE, priv))
106
                        return (CREDS_FAIL);
107
        }
108
# endif
109
110
        errno = 0;
111
        if (getpeerucred(fd, &ucredp))
112
                return (CREDS_FAIL);
113
        *uid = ucred_geteuid(ucredp);
114
        *gid = ucred_getegid(ucredp);
115
116
# if defined(HAVE_SETPPRIV)
117
        if (priv != NULL)
118
                AZ(setppriv(PRIV_OFF, PRIV_EFFECTIVE, priv)); // waive
119
# endif
120
121
        return (0);
122
#else
123
        (void) fd;
124
        (void) uid;
125
        (void) gid;
126
        return (NOT_SUPPORTED);
127
#endif
128
129 200
}