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