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 ERRNOTUDS(ctx) \
52
        ERR((ctx), "not listening on a Unix domain socket")
53
54
#define FAIL_SUPPORT(ctx) \
55
        FAIL((ctx), "not supported on this platform")
56
57
#define ERRNOCREDS(ctx) \
58
        VERR((ctx), "could not read peer credentials: %s", strerror(errno))
59
60
#define ERRNOMEM(ctx) \
61
        ERR((ctx), "out of space")
62
63
static struct sess *
64 400
get_sp(VRT_CTX)
65
{
66
        struct sess *sp;
67
68 400
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
69
70 400
        if (ctx->req) {
71 200
                CHECK_OBJ(ctx->req, REQ_MAGIC);
72 200
                sp = ctx->req->sp;
73 200
        } else {
74 200
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
75 200
                sp = ctx->bo->sp;
76
        }
77 400
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
78 400
        CHECK_OBJ_NOTNULL(sp->listen_sock, LISTEN_SOCK_MAGIC);
79 400
        return (sp);
80
}
81
82
#define NUM_FUNC(func)                                  \
83
VCL_INT                                                 \
84
vmod_##func(VRT_CTX)                                    \
85
{                                                       \
86
        struct sess *sp;                                \
87
        uid_t uid;                                      \
88
        gid_t gid;                                      \
89
        int ret;                                        \
90
                                                        \
91
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
92
        AZ(ctx->method & VCL_MET_TASK_H);       \
93
                                                        \
94
        sp = get_sp(ctx);                               \
95
        if (!sp->listen_sock->uds) {                    \
96
                ERRNOTUDS(ctx);                         \
97
                return (-1);                            \
98
        }                                               \
99
                                                        \
100
        ret = get_ids(sp->fd, &uid, &gid);              \
101
        if (ret == 0)                                   \
102
                return (func);                          \
103
                                                        \
104
        if (ret == NOT_SUPPORTED)                       \
105
                FAIL_SUPPORT(ctx);                      \
106
        else if (ret == CREDS_FAIL)                     \
107
                ERRNOCREDS(ctx);                        \
108
        return (-1);                                    \
109
}
110
111 200
NUM_FUNC(uid)
112 200
NUM_FUNC(gid)
113
114
#define NAME_FUNC(func, type, get, id, fld)                     \
115
VCL_STRING                                                      \
116
vmod_##func(VRT_CTX)                                            \
117
{                                                               \
118
        struct type *s;                                         \
119
        VCL_INT ret;                                            \
120
        VCL_STRING name;                                        \
121
                                                                \
122
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
123
        ret = vmod_##id(ctx);                                   \
124
        if (ret == -1)                                          \
125
                return (NULL);                                  \
126
                                                                \
127
        errno = 0;                                              \
128
        s = get((id##_t) ret);                                  \
129
        if (s == NULL) {                                        \
130
                ERRNOCREDS(ctx);                                \
131
                return (NULL);                                  \
132
        }                                                       \
133
        if ((name = WS_Copy(ctx->ws, s->fld, -1)) == NULL) {    \
134
                ERRNOMEM(ctx);                                  \
135
                return (NULL);                                  \
136
        }                                                       \
137
        return (name);                                          \
138
}
139
140 100
NAME_FUNC(user, passwd, getpwuid, uid, pw_name)
141 100
NAME_FUNC(group, group, getgrgid, gid, gr_name)