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