]> granicus.if.org Git - sudo/blob - plugins/group_file/plugin_test.c
129264a1566693cd80a19dcb91005acba156e797
[sudo] / plugins / group_file / plugin_test.c
1 /*
2  * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@sudo.ws>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /*
18  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
19  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
20  */
21
22 #include <sys/types.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <ctype.h>
30 #include <dlfcn.h>
31 #include <errno.h>
32 #include <limits.h>
33 #include <pwd.h>
34
35 #include "sudo_plugin.h"
36
37 __dso_public int main(int argc, char *argv[]);
38
39 /*
40  * Simple driver to test sudoer group plugins.
41  * usage: plugin_test [-p "plugin.so plugin_args ..."] user:group ...
42  */
43
44 static void *group_handle;
45 static struct sudoers_group_plugin *group_plugin;
46
47 static int
48 plugin_printf(int msg_type, const char *fmt, ...)
49 {
50     va_list ap;
51     FILE *fp;
52             
53     switch (msg_type) {
54     case SUDO_CONV_INFO_MSG:
55         fp = stdout;
56         break;
57     case SUDO_CONV_ERROR_MSG:
58         fp = stderr;
59         break;
60     default:
61         errno = EINVAL;
62         return -1;
63     }
64
65     va_start(ap, fmt);
66     vfprintf(fp, fmt, ap);
67     va_end(ap);
68
69     return 0;
70 }
71
72 /*
73  * Load the specified plugin and run its init function.
74  * Returns -1 if unable to open the plugin, else it returns
75  * the value from the plugin's init function.
76  */
77 static int
78 group_plugin_load(char *plugin_info)
79 {
80     char *args, path[PATH_MAX], savedch;
81     char **argv = NULL;
82     int rc;
83
84     /*
85      * Fill in .so path and split out args (if any).
86      */
87     if ((args = strpbrk(plugin_info, " \t")) != NULL) {
88         savedch = *args;
89         *args = '\0';
90     }
91     strncpy(path, plugin_info, sizeof(path) - 1);
92     path[sizeof(path) - 1] = '\0';
93     if (args != NULL)
94         *args++ = savedch;
95
96     /* Open plugin and map in symbol. */
97     group_handle = dlopen(path, RTLD_LAZY);
98     if (!group_handle) {
99         fprintf(stderr, "unable to dlopen %s: %s\n", path, dlerror());
100         return -1;
101     }
102     group_plugin = dlsym(group_handle, "group_plugin");
103     if (group_plugin == NULL) {
104         fprintf(stderr, "unable to find symbol \"group_plugin\" in %s\n", path);
105         return -1;
106     }
107
108     if (SUDO_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
109         fprintf(stderr,
110             "%s: incompatible group plugin major version %d, expected %d\n",
111             path, SUDO_API_VERSION_GET_MAJOR(group_plugin->version),
112             GROUP_API_VERSION_MAJOR);
113         return -1;
114     }
115
116     /*
117      * Split args into a vector if specified.
118      */
119     if (args != NULL) {
120         int ac = 0, wasblank = 1;
121         char *cp;
122
123         for (cp = args; *cp != '\0'; cp++) {
124             if (isblank((unsigned char)*cp)) {
125                 wasblank = 1;
126             } else if (wasblank) {
127                 wasblank = 0;
128                 ac++;
129             }
130         }
131         if (ac != 0)    {
132             char *last;
133
134             argv = malloc(ac * sizeof(char *));
135             if (argv == NULL) {
136                 perror(NULL);
137                 return -1;
138             }
139             ac = 0;
140             for ((cp = strtok_r(args, " \t", &last)); cp != NULL; (cp = strtok_r(NULL, " \t", &last)))
141                 argv[ac++] = cp;
142         }
143     }
144
145     rc = (group_plugin->init)(GROUP_API_VERSION, plugin_printf, argv);
146
147     free(argv);
148
149     return rc;
150 }
151
152 static void
153 group_plugin_unload(void)
154 {
155     (group_plugin->cleanup)();
156     dlclose(group_handle);
157     group_handle = NULL;
158 }
159
160 static int
161 group_plugin_query(const char *user, const char *group,
162     const struct passwd *pwd)
163 {
164     return (group_plugin->query)(user, group, pwd);
165 }
166
167 static void
168 usage(void)
169 {
170     fprintf(stderr,
171         "usage: plugin_test [-p \"plugin.so plugin_args ...\"] user:group ...\n");
172     exit(1);
173 }
174
175 int
176 main(int argc, char *argv[])
177 {
178     int ch, i, found;
179     char *plugin = "group_file.so";
180     char *user, *group;
181     struct passwd *pwd;
182
183     while ((ch = getopt(argc, argv, "p:")) != -1) {
184         switch (ch) {
185         case 'p':
186             plugin = optarg;
187             break;
188         default:
189             usage();
190         }
191     }
192     argc -= optind;
193     argv += optind;
194
195     if (argc < 1)
196         usage();
197
198     if (group_plugin_load(plugin) != 1) {
199         fprintf(stderr, "unable to load plugin: %s\n", plugin);
200         exit(1);
201     }
202
203     for (i = 0; argv[i] != NULL; i++) {
204         user = argv[i];
205         group = strchr(argv[i], ':');
206         if (group == NULL)
207             continue;
208         *group++ = '\0';
209         pwd = getpwnam(user);
210         found = group_plugin_query(user, group, pwd);
211         printf("user %s %s in group %s\n", user, found ? "is" : "NOT ", group);
212     }
213     group_plugin_unload();
214
215     exit(0);
216 }
217