varnish-cache/vmod/vmod_unix.c
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 "config.h"
31
32
#include <pwd.h>
33
#include <grp.h>
34
#include <string.h>
35
36
#include "cache/cache.h"
37
#include "vcl.h"
38
#include "common/heritage.h"
39
40
#include "vmod_unix_cred_compat.h"
41
#include "vcc_unix_if.h"
42
43
#define FAIL(ctx, msg) \
44
        VRT_fail((ctx), "vmod unix failure: " msg)
45
46
#define ERR(ctx, msg) \
47
        VSLb((ctx)->vsl, SLT_VCL_Error, "vmod unix error: " msg)
48
49
#define VERR(ctx, fmt, ...) \
50
        VSLb((ctx)->vsl, SLT_VCL_Error, "vmod unix error: " fmt, __VA_ARGS__)
51
52
#define FAILNOINIT(ctx) \
53
        FAIL((ctx), "may not be called in vcl_init or vcl_fini")
54
55
#define ERRNOTUDS(ctx) \
56
        ERR((ctx), "not listening on a Unix domain socket")
57
58
#define FAIL_SUPPORT(ctx) \
59
        FAIL((ctx), "not supported on this platform")
60
61
#define ERRNOCREDS(ctx) \
62
        VERR((ctx), "could not read peer credentials: %s", strerror(errno))
63
64
#define ERRNOMEM(ctx) \
65
        ERR((ctx), "out of space")
66
67
static struct sess *
68 352
get_sp(VRT_CTX)
69
{
70
        struct sess *sp;
71
72 352
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
73
74 352
        if (ctx->req) {
75 176
                CHECK_OBJ(ctx->req, REQ_MAGIC);
76 176
                sp = ctx->req->sp;
77 176
        } else {
78 176
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
79 176
                sp = ctx->bo->sp;
80
        }
81 352
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
82 352
        CHECK_OBJ_NOTNULL(sp->listen_sock, LISTEN_SOCK_MAGIC);
83 352
        return (sp);
84
}
85
86
#define NUM_FUNC(func)                                  \
87
VCL_INT                                                 \
88
vmod_##func(VRT_CTX)                                    \
89
{                                                       \
90
        struct sess *sp;                                \
91
        uid_t uid;                                      \
92
        gid_t gid;                                      \
93
        int ret;                                        \
94
                                                        \
95
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
96
        if ((ctx->method & VCL_MET_TASK_H) != 0) {      \
97
                FAILNOINIT(ctx);                        \
98
                return (-1);                            \
99
        }                                               \
100
                                                        \
101
        sp = get_sp(ctx);                               \
102
        if (!sp->listen_sock->uds) {                    \
103
                ERRNOTUDS(ctx);                         \
104
                return (-1);                            \
105
        }                                               \
106
                                                        \
107
        ret = get_ids(sp->fd, &uid, &gid);              \
108
        if (ret == 0)                                   \
109
                return (func);                          \
110
                                                        \
111
        if (ret == NOT_SUPPORTED)                       \
112
                FAIL_SUPPORT(ctx);                      \
113
        else if (ret == CREDS_FAIL)                     \
114
                ERRNOCREDS(ctx);                        \
115
        return (-1);                                    \
116
}
117
118 220
NUM_FUNC(uid)
119 220
NUM_FUNC(gid)
120
121
#define NAME_FUNC(func, type, get, id, fld)                     \
122
VCL_STRING                                                      \
123
vmod_##func(VRT_CTX)                                            \
124
{                                                               \
125
        struct type *s;                                         \
126
        VCL_INT ret;                                            \
127
        VCL_STRING name;                                        \
128
                                                                \
129
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
130
        ret = vmod_##id(ctx);                                   \
131
        if (ret == -1)                                          \
132
                return (NULL);                                  \
133
                                                                \
134
        errno = 0;                                              \
135
        s = get((id##_t) ret);                                  \
136
        if (s == NULL) {                                        \
137
                ERRNOCREDS(ctx);                                \
138
                return (NULL);                                  \
139
        }                                                       \
140
        if ((name = WS_Copy(ctx->ws, s->fld, -1)) == NULL) {    \
141
                ERRNOMEM(ctx);                                  \
142
                return (NULL);                                  \
143
        }                                                       \
144
        return (name);                                          \
145
}
146
147 110
NAME_FUNC(user, passwd, getpwuid, uid, pw_name)
148 110
NAME_FUNC(group, group, getgrgid, gid, gr_name)