1 /* Tests for name switch cache daemon (nscd) door wrapper. */
2 
3 #include "config.h"
4 
5 #include <assert.h>
6 #include <ctype.h>
7 #include <door.h>
8 #include <fcntl.h>
9 #include <inttypes.h>
10 #include <nss_dbdefs.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <strings.h>
14 #include <unistd.h>
15 #include <sys/mman.h>
16 
17 #if defined(SOLARIS_NSCD_DOOR_SYSTEM_VOLATILE)
18 #define DOOR_FILE "/system/volatile/name_service_door"
19 #else
20 #define DOOR_FILE "/var/run/name_service_door"
21 #endif
22 
23 #define HEADER(file, test_name) \
24    fprintf(file, "---------------------------------------------------------\n"  \
25                  "%s\n"                                                         \
26                  "---------------------------------------------------------\n", \
27                  test_name);
28 
29 
30 static long x0;
31 
32 /* It's possible that the system allocated a new memory for rbuf.
33    Unmap it if it is the case. */
handle_rbuf(door_arg_t * params,void * buf)34 static int handle_rbuf(door_arg_t *params, void *buf)
35 {
36    if (params->rbuf != buf) {
37       if (munmap(params->rbuf, params->rsize) != 0) {
38          perror("munmap");
39          return EINVAL;
40       }
41    }
42 
43    return 0;
44 }
45 
46 __attribute__((noinline))
test_app_small_request(int did)47 static int test_app_small_request(int did)
48 {
49    /* Set call parameters. */
50    size_t buf_size = sizeof(uint32_t);
51    char *buf = malloc(buf_size);
52    assert(buf != NULL);
53 
54    nss_pheader_t *header = (nss_pheader_t *) buf;
55    header->nsc_callnumber = x0 + NSCD_GETENT;
56 
57    door_arg_t params;
58    params.data_ptr = buf;
59    params.data_size = buf_size;
60    params.desc_ptr = NULL;
61    params.desc_num = 0;
62    params.rbuf = buf;
63    params.rsize = buf_size;
64 
65    /* Make the call. */
66    if (door_call(did, &params) != 0) {
67       return errno;
68    }
69 
70    return handle_rbuf(&params, buf);
71 }
72 
73 __attribute__((noinline))
test_app_uninitialized_request(int did)74 static int test_app_uninitialized_request(int did)
75 {
76    /* Set call parameters. */
77    size_t buf_size = sizeof(nss_pheader_t) + sizeof(nss_dbd_t);
78    char *buf = malloc(buf_size);
79    assert(buf != NULL);
80 
81    nss_pheader_t *header = (nss_pheader_t *) buf;
82    header->nsc_callnumber = x0 + NSCD_GETENT;
83    header->dbd_off = x0 + sizeof(nss_pheader_t);
84    header->dbd_len = x0 + sizeof(nss_dbd_t);
85    nss_dbd_t *dbd = (nss_dbd_t *) (buf + sizeof(nss_pheader_t));
86    dbd->flags = x0;
87    dbd->o_name = x0 + 100;
88    dbd->o_config_name = x0 + 100;
89    dbd->o_default_config = x0 + 100;
90    header->key_off = x0 + sizeof(nss_pheader_t) + sizeof(nss_dbd_t);
91    header->key_len = x0 + 1; // one byte past the end of 'buf'
92    header->pbufsiz = x0 + 10000000;
93 
94    door_arg_t params;
95    params.data_ptr = buf;
96    params.data_size = buf_size;
97    params.desc_ptr = NULL;
98    params.desc_num = 0;
99    params.rbuf = buf;
100    params.rsize = buf_size;
101 
102    /* Make the call. */
103    if (door_call(did, &params) != 0) {
104       return errno;
105    }
106 
107    /* Check definedness of response attributes ... */
108    int x = 0;
109    if (header->p_status != NSS_SUCCESS) x = -1; else x = -2;
110    if (header->p_herrno != 0) x = -2; else x = -3;
111    if (header->key_off != 0) x = -4; else x = -5;
112    if (header->key_len != 0) x = -6; else x = -7;
113    if (header->data_off != 0) x = -8; else x = -9;
114    if (header->data_len != 0) x = -10; else x = -11;
115    /* ... and now one which is not defined. */
116    if (header->reserved1 != 0) x = -12; else x = -13;
117 
118    handle_rbuf(&params, buf);
119    return x;
120 }
121 
122 __attribute__((noinline))
test_app_proto_icmp(int did)123 static int test_app_proto_icmp(int did)
124 {
125    door_arg_t params;
126    char buf[16384];
127 
128    /* Set call parameters. */
129    nss_pheader_t *header = (nss_pheader_t *) buf;
130    header->nsc_callnumber = NSCD_SEARCH;
131    header->p_ruid = getuid();
132    header->p_euid = geteuid();
133    header->p_version = NSCD_HEADER_REV;
134    header->p_status = 0;
135    header->p_errno = 0;
136    header->p_herrno = 0;
137    header->libpriv = 0;
138    header->nss_dbop = NSS_DBOP_PROTOCOLS_BYNAME;
139 
140    size_t name_len = strlen(NSS_DBNAM_PROTOCOLS);
141    size_t default_config_len = strlen(NSS_FILES_ONLY);
142    header->dbd_off = sizeof(nss_pheader_t);
143    header->dbd_len = sizeof(nss_dbd_t) + name_len + 1 + default_config_len + 1;
144    nss_dbd_t *dbd = (nss_dbd_t *) (buf + sizeof(nss_pheader_t));
145    dbd->o_name = sizeof(nss_dbd_t);
146    dbd->o_config_name = 0;
147    dbd->o_default_config = dbd->o_name + name_len + 1;
148    dbd->flags = 0;
149    strcpy(buf + header->dbd_off + dbd->o_name, NSS_DBNAM_PROTOCOLS);
150    strcpy(buf + header->dbd_off + dbd->o_default_config,
151           NSS_DEFCONF_PROTOCOLS);
152 
153    name_len = strlen("icmp");
154    header->key_off = header->dbd_off + ROUND_UP(header->dbd_len, sizeof(nssuint_t));
155    header->key_len = name_len + 1;
156    strcpy(buf + header->key_off, "icmp");
157 
158    header->data_off = header->key_off + ROUND_UP(header->key_len, sizeof(nssuint_t));
159    header->data_len = 0;
160    header->pbufsiz = header->data_off + header->data_len;
161 
162    params.data_ptr = buf;
163    params.data_size = header->pbufsiz;
164    params.desc_ptr = NULL;
165    params.desc_num = 0;
166    params.rbuf = buf;
167    params.rsize = sizeof(buf);
168 
169    /* Sanity checks on the nss_pheader_t header. */
170    assert(header->p_version == NSCD_HEADER_REV);
171    assert(header->dbd_off == sizeof(nss_pheader_t));
172    assert((params.data_size & 3) == 0);
173    assert((header->dbd_off & 3) == 0);
174    assert((header->key_off & 3) == 0);
175    assert((header->data_off & 3) == 0);
176    assert(header->data_off == params.data_size);
177    nssuint_t l1 = header->key_off - header-> dbd_off;
178    assert(l1 >= header->dbd_len);
179    nssuint_t l2 = header->data_off - header->key_off;
180    assert(l2 >= header->key_len);
181    assert(sizeof(nss_pheader_t) + l1 + l2 == header->data_off);
182    assert(header->data_off + header->data_len == header->pbufsiz);
183 
184    /* Make the call. */
185    if (door_call(did, &params) != 0) {
186       return errno;
187    }
188 
189    /* Print response attributes. */
190    HEADER(stdout, "app_proto_icmp");
191    printf("status=%u\n", header->p_status);
192    printf("errno=%u\n", header->p_errno);
193    printf("herrno=%u\n", header->p_herrno);
194    printf("bufsiz=%" PRIu64 "\n", header->pbufsiz);
195    printf("dbd_off=%" PRIu64 " dbd_len=%" PRIu64 "\n",
196           header->dbd_off, header->dbd_len);
197    printf("key_off=%" PRIu64 " key_len=%" PRIu64 "\n",
198           header->key_off, header->key_len);
199    printf("data_off=%" PRIu64 " data_len=%" PRIu64 "\n",
200           header->data_off, header->data_len);
201    printf("ext_off=%" PRIu64 " ext_len=%" PRIu64 "\n",
202           header->ext_off, header->ext_len);
203    printf("key=%s\n", buf + header->key_off);
204 
205    /* Parse response proto data. */
206    char *p = buf + header->data_off;
207    char *limit = p + header->data_len;
208 
209    while ((p < limit) && isspace(*p))
210       p++;
211    char *name_start = p;
212    while ((p < limit) && !isspace(*p))
213       p++; // skip over the name
214    name_len = p - name_start;
215 
216    while ((p < limit) && isspace(*p))
217       p++;
218    char *number_start = p;
219    do {
220       p++; // skip over the proto number
221    } while ((p < limit) && !isspace(*p));
222    size_t number_len = p - number_start;
223 
224    while ((p < limit) && isspace(*p))
225       p++;
226    char *aliases_start = p;
227    while ((p < limit) && !isspace(*p))
228       p++; // skip over the aliases
229    size_t aliases_len = p - aliases_start;
230 
231    printf("data: name=%.*s number=%.*s aliases=%.*s\n",
232       (int) name_len, name_start, (int) number_len, number_start,
233       (int) aliases_len, aliases_start);
234 
235    return handle_rbuf(&params, buf);
236 }
237 
main(int argc,const char * argv[])238 int main(int argc, const char *argv[])
239 {
240    /* Uninitialised, but we know px[0] is 0x0. */
241    long *px = malloc(sizeof(long));
242    x0 = px[0];
243 
244    int did = open(DOOR_FILE, O_RDONLY);
245    if (did < 0) {
246       perror("open " DOOR_FILE);
247       fprintf(stderr, "Make sure the name service switch daemon (nscd) "
248               "is running.\n");
249       return 1;
250    }
251 
252    struct door_info info;
253    if (door_info(did, &info) != 0) {
254       perror("door_info " DOOR_FILE);
255       close(did);
256       return 1;
257    }
258 
259    HEADER(stderr, "app_small_request");
260    test_app_small_request(did);
261 
262    HEADER(stderr, "app_uninitialized_request");
263    test_app_uninitialized_request(did);
264 
265    HEADER(stderr, "app_proto_icmp");
266    test_app_proto_icmp(did);
267 
268    close(did);
269 
270    return 0;
271 }
272 
273