/[pdpsoft]/trunk/grid-mw-security/glexec/util/lcaslcmaps_getaccount_cli/lcaslcmaps_getaccount_cli.c
ViewVC logotype

Contents of /trunk/grid-mw-security/glexec/util/lcaslcmaps_getaccount_cli/lcaslcmaps_getaccount_cli.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1837 - (show annotations) (download) (as text)
Tue Jul 6 12:24:17 2010 UTC (11 years, 6 months ago) by msalle
File MIME type: text/x-chdr
File size: 15331 byte(s)
Fix for specifying -s twice (it closed stderr...).


1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <string.h>
5 #include <errno.h>
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11
12 #include <pwd.h>
13 #include <grp.h>
14
15 #include <dlfcn.h>
16
17 /* Define getMajorVersion() etc. to prevent a bug from voms */
18 int getMajorVersionNumber() { return 0; }
19 int getMinorVersionNumber() { return 0; }
20 int getPatchVersionNumber() { return 0; }
21
22 /* lcas_request_t is defined in lcas_types.h, can just re-typedef it here. */
23 #if 0
24 /*#include "lcas_types.h"*/
25 #else
26 typedef char *lcas_request_t;
27 #endif
28
29 /* lcmaps_account_info_t is defined in lcmaps_account.h,
30 * can just re-typedef it here. */
31 #if 0
32 #include "lcmaps_account.h"
33 #else
34 typedef struct lcmaps_account_info_s
35 {
36 uid_t uid; /* the uid of the local account */
37 gid_t * pgid_list; /* the list of primary gids */
38 int npgid; /* the number of primary gids found */
39 gid_t * sgid_list; /* the list of secondary gids */
40 int nsgid; /* the number of secondary gids found */
41 char * poolindex; /* the pool index */
42 } lcmaps_account_info_t;
43 #endif
44
45 /* Define to have getopt() behave POSIX correctly */
46 #define POSIXLY_CORRECT
47
48 /* Struct containing all the lcmaps functions, will be filled using dlsym() */
49 typedef struct {
50 void *handle; /* Needed for dlclose() */
51 int (*lcmaps_init)(FILE*);
52 int (*lcmaps_account_info_init)(lcmaps_account_info_t*);
53 int (*lcmaps_return_account_from_pem)(char*,int,lcmaps_account_info_t*);
54 int (*lcmaps_term)(void);
55 } lcmaps_library_t;
56
57 /* Struct containing all the lcas functions, will be filled using dlsym() */
58 typedef struct {
59 void *handle; /* Needed for dlclose() */
60 int (*lcas_init)(FILE*);
61 int (*lcas_pem)(char*,lcas_request_t);
62 int (*lcas_term)(void);
63 } lcas_library_t;
64
65 /* Parses the options for LCMAPS and opens the logfile when needed */
66 int lcmaps_set_vars(char *options,FILE **log) {
67 char *var=options,*value,*end,*pos;
68
69 /* If first char of options is a - it's actually the next main option */
70 if (options[0]=='-')
71 return 0;
72
73 do {
74 /* Find end of current var=value pair */
75 end=strchr(var, ',');
76 if (end!=NULL) end[0]='\0';
77 /* Find end of variable name */
78 pos=strchr(var,'=');
79 if (pos==NULL)
80 fprintf(stderr,"Unrecognized element '%s'\n", var);
81 else {
82 pos[0]='\0';
83 value=pos+1;
84 /* Find the variable */
85 if (strcmp(var,"debug")==0)
86 setenv("LCMAPS_DEBUG_LEVEL",value,1);
87 /* else if (strcmp(var,"log")==0)
88 setenv("LCMAPS_LOG_LEVEL",value,1);*/
89 else if (strcmp(var,"policy")==0)
90 setenv("LCMAPS_POLICY_NAME",value,1);
91 else if (strcmp(var,"db")==0)
92 setenv("LCMAPS_DB_FILE",value,1);
93 else if (strcmp(var,"file")==0) {
94 /* Only open when not already linked to stderr */
95 if (*log==NULL) {
96 if ( (*log=fopen(value,"a"))==NULL)
97 fprintf(stderr,"Cannot open %s: %s\n",
98 value,strerror(errno));
99 }
100 }
101 else
102 fprintf(stderr,"Unrecognized option '%s'\n",var);
103 /* reset value at pos */
104 pos[0]='=';
105 }
106 if (end!=NULL) {
107 /* reset value at end */
108 end[0]=',';
109 /* advance to next option */
110 var=end+1;
111 }
112 } while (end!=NULL);
113 return 0;
114 }
115
116 /* Prints contents of account */
117 void lcmaps_print_account(lcmaps_account_info_t* account) {
118 int i;
119 struct passwd *pw;
120 struct group *gr;
121
122 /* Check if there is anything */
123 if (account->uid==-1) {
124 printf("Account info is empty.\n");
125 return;
126 }
127 /* UID / username */
128 pw=getpwuid(account->uid);
129 printf("uid=%d(%s)\n",account->uid,pw ? pw->pw_name : "undefined");
130 /* Primary groups */
131 printf("primary gids: %d\n",account->npgid);
132 for (i=0; i<account->npgid; i++) {
133 gr=getgrgid(account->pgid_list[i]);
134 printf("pgid[%d]=%d(%s)\n",i,
135 account->pgid_list[i],
136 gr ? gr->gr_name : "undefined");
137 }
138 /* Secondary groups */
139 printf("secondary gids: %d\n",account->nsgid);
140 for (i=0; i<account->nsgid; i++) {
141 gr=getgrgid(account->sgid_list[i]);
142 printf("sgid[%d]=%d(%s)\n",i,
143 account->sgid_list[i],
144 gr ? gr->gr_name : "undefined");
145 }
146 /* Poolindex */
147 printf("poolindex=%s\n",
148 (account->poolindex)!=NULL ? account->poolindex : "undefined");
149 }
150
151 /* Dynamically loads LCMAPS library and all needed symbols */
152 int loadlcmaps(lcmaps_library_t *lib) {
153 void *handle;
154
155 /* Load the library */
156 if ( (lib->handle=handle=dlopen("liblcmaps_return_account_from_pem.so",
157 RTLD_NOW | RTLD_GLOBAL))==NULL ) {
158 fprintf(stderr,"Error: %s\n",dlerror());
159 return 1;
160 }
161
162 /* Load functions */
163 if ( (lib->lcmaps_init=
164 (int (*)(FILE*))
165 dlsym(handle,"lcmaps_init"))==NULL ||
166 (lib->lcmaps_account_info_init=
167 (int (*)(lcmaps_account_info_t*))
168 dlsym(handle,"lcmaps_account_info_init"))==NULL ||
169 (lib->lcmaps_return_account_from_pem=
170 (int (*)(char*,int,lcmaps_account_info_t*))
171 dlsym(handle,"lcmaps_return_account_from_pem"))==NULL ||
172 (lib->lcmaps_term=
173 (int (*)(void))
174 dlsym(handle,"lcmaps_term"))==NULL ) {
175 fprintf(stderr,"Error: %s\n",dlerror());
176 dlclose(handle);
177 return 1;
178 }
179
180 return 0;
181 }
182
183 /* Loads LCMAPS library and does a run, for given pemstring and to logfile or
184 * syslog when logfile is NULL. */
185 int lcmaps(char *pemstring,FILE *logfile) {
186 int rc;
187 lcmaps_library_t lib;
188 lcmaps_account_info_t account;
189
190 /* Load lcmaps library and symbols */
191 if (loadlcmaps(&lib))
192 return 1;
193
194 /* Do a run */
195 if ( (rc=lib.lcmaps_init(logfile)) ) {
196 fprintf(stderr,"lcmaps_init() failed\n");
197 goto finalize;
198 }
199 if ( (rc=lib.lcmaps_account_info_init(&account)) ) {
200 fprintf(stderr,"lcmaps_account_info_init() failed.\n");
201 goto finalize;
202 }
203 if ( (rc=lib.lcmaps_return_account_from_pem(pemstring,-1,&account)) ) {
204 fprintf(stderr,"lcmaps_return_account_from_pem() failed.\n");
205 goto finalize;
206 }
207 if ( (rc=lib.lcmaps_term()) ) {
208 fprintf(stderr,"lcmaps_term() failed.\n");
209 goto finalize;
210 }
211 /* LCMAPS finished succesfully */
212 rc=0;
213 printf("LCMAPS succeeded.\n");
214
215 /* Print contents of account */
216 lcmaps_print_account(&account);
217
218 finalize:
219 /* Close library */
220 dlclose(lib.handle);
221 return rc;
222 }
223
224 /* Parses the options for LCAS and opens the logfile when needed */
225 int lcas_set_vars(char *options,char **rsl,FILE **log) {
226 char *var=options,*value,*end,*pos;
227
228 /* If first char of options is a - it's actually the next main option */
229 if (options[0]=='-')
230 return 0;
231
232 do {
233 /* Find end of current var=value pair */
234 end=strchr(var, ',');
235 if (end!=NULL) end[0]='\0';
236 /* Find end of variable name */
237 pos=strchr(var,'=');
238 if (pos==NULL)
239 fprintf(stderr,"Unrecognized element '%s'\n", var);
240 else {
241 pos[0]='\0';
242 value=pos+1;
243 /* Find the variable */
244 if (strcmp(var,"debug")==0)
245 setenv("LCAS_DEBUG_LEVEL",value,1);
246 /* else if (strcmp(var,"log")==0)
247 setenv("LCAS_LOG_LEVEL",value,1);*/
248 else if (strcmp(var,"db")==0)
249 setenv("LCAS_DB_FILE",value,1);
250 else if (strcmp(var,"rsl")==0)
251 *rsl=strdup(value);
252 else if (strcmp(var,"file")==0) {
253 /* Only open when not already linked to stderr */
254 if (*log==NULL) {
255 if ( (*log=fopen(value,"a"))==NULL)
256 fprintf(stderr,"Cannot open %s: %s\n",
257 value,strerror(errno));
258 }
259 }
260 else
261 fprintf(stderr,"Unrecognized option '%s'\n",var);
262 /* reset value at pos */
263 pos[0]='=';
264 }
265 if (end!=NULL) {
266 /* reset value at end */
267 end[0]=',';
268 /* advance to next option */
269 var=end+1;
270 }
271 } while (end!=NULL);
272 return 0;
273 }
274 /* Dynamically loads LCAS library and all needed symbols */
275 int loadlcas(lcas_library_t *lib) {
276 void *handle;
277
278 /* Load the library */
279 if ( (lib->handle=handle=
280 dlopen("liblcas.so",RTLD_NOW | RTLD_GLOBAL))==NULL ) {
281 fprintf(stderr,"Error: %s\n",dlerror());
282 return 1;
283 }
284
285 /* Load functions */
286 if ( (lib->lcas_init=
287 (int (*)(FILE*))dlsym(handle,"lcas_init"))==NULL ||
288 (lib->lcas_pem=
289 (int (*)(char*,lcas_request_t))dlsym(handle,"lcas_pem"))==NULL ||
290 (lib->lcas_term=
291 (int (*)(void))dlsym(handle,"lcas_term"))==NULL ) {
292 fprintf(stderr,"Error: %s\n",dlerror());
293 dlclose(handle);
294 return 1;
295 }
296
297 return 0;
298 }
299
300 /* Loads LCAS library and does a run, for given pemstring and to logfile or
301 * syslog when logfile is NULL and given rsl (=cmd + argus) */
302 int lcas(char *pemstring,FILE *logfile,char *rsl) {
303 int rc;
304 lcas_library_t lib;
305 lcas_request_t request;
306
307 request=(lcas_request_t)rsl;
308
309 /* Load library and symbols */
310 if (loadlcas(&lib))
311 return 1;
312
313 /* Do a run */
314 if ( (rc=lib.lcas_init(logfile)) ) {
315 fprintf(stderr,"lcas_init() failed\n"); goto finalize;
316 }
317 if ( (rc=lib.lcas_pem(pemstring,request)) ) {
318 fprintf(stderr,"lcas_pem() failed.\n"); goto finalize;
319 }
320 if ( (rc=lib.lcas_term()) ) {
321 fprintf(stderr,"lcas_term() failed.\n"); goto finalize;
322 }
323 printf("LCAS succeeded.\n");
324
325 finalize:
326 /* Close library */
327 dlclose(lib.handle);
328 return rc;
329 }
330
331 /* Reads in user proxy (on which mapping is based) from filename */
332 char *readproxy(const char *filename) {
333 int fd,size;
334 char *pemstring;
335 struct stat st;
336
337 /* Open file and get size */
338 if ((fd=open(filename,O_RDONLY))==-1 || fstat(fd,&st)==-1) {
339 fprintf(stderr,"Error: Cannot open or stat file %s: %s\n",
340 filename, strerror(errno));
341 exit(1);
342 }
343 /* Reserve memory */
344 if ((pemstring=(char *)malloc((size_t)(st.st_size+sizeof(char))))==NULL) {
345 fprintf(stderr,"Error: Cannot malloc %d bytes for pemstring\n",
346 (int)st.st_size);
347 exit(1);
348 }
349 /* Read file */
350 size=read(fd,pemstring,(size_t)st.st_size);
351 if (size!=st.st_size) {
352 fprintf(stderr,"Error: Number of bytes read %d != size %d\n",
353 size,(int)st.st_size);
354 exit(1);
355 }
356 /* Close file */
357 close(fd);
358 /* Add '\0' and return */
359 pemstring[size]='\0';
360 return pemstring;
361 }
362
363 /* Prints out usage information */
364 void usage(char *prog) {
365 int uid=(int)getuid();
366
367 printf("Usage: %s [options]\n\n",prog);
368 printf("Valid options are:\n");
369 printf(" -h print this help text.\n");
370 printf("\n -s send output to stderr instead of syslog or file.\n");
371 printf(" -q quiet output (no warnings).\n");
372 printf(" -p<file> read pemstring from given file.\n");
373 printf(" -x<file> set or override X509_USER_PROXY to given file.\n");
374 printf("\n -V<dir> set or override X509_VOMS_DIR to given dir.\n");
375 printf(" -C<dir> set or override X509_CERT_DIR to given dir.\n");
376 printf("\n -L[opts] run LCAS with given options: ");
377 printf("<var>=<value>,<var=value>,...\n");
378 printf(" db=<file> set or override LCAS_DB_FILE.\n");
379 printf(" debug=<level> set or override LCAS_DEBUG_LEVEL.\n");
380 /* printf(" log=<level> set or override LCAS_LOG_LEVEL (which is ignored).\n");*/
381 printf(" rsl=<string> set rsl string (needs to be quoted).\n");
382 printf(" file=<file> send debug/log output to file instead of ");
383 printf("syslog, ignored\n when -s is specified.\n");
384 printf("\n -l[opts] run LCMAPS with given options: ");
385 printf("<var>=<value>,<var=value>,...\n");
386 printf(" db=<file> set or override LCMAPS_DB_FILE.\n");
387 printf(" policy=<name> set or override LCMAPS_POLICY_NAME.\n");
388 printf(" debug=<level> set or override LCMAPS_DEBUG_LEVEL.\n");
389 /* printf(" log=<level> set or override LCMAPS_LOG_LEVEL (which is ignored).\n");*/
390 printf(" file=<file> send debug/log output to file instead of ");
391 printf("syslog, ignored\n when -s is specified.\n");
392 printf("\nExample:\n");
393 printf(" %s -s -p/tmp/x509up_u%d -x/tmp/x509up_u%d \\\n",prog,uid,uid);
394 printf(" -L debug=5,db=/tmp/lcas.db \\\n");
395 printf(" -l policy=glexec_get_account,debug=5,db=/tmp/lcmaps.db\n");
396 printf("\nNotes on reproducing gLExec behaviour:\n");
397 printf("- gLExec uses an LCMAPS policy named 'glexec_get_account'\n");
398 printf("- the proxy specified with -p is the analog of the GLEXEC_CLIENT_CERT.\n");
399
400 exit(0);
401 }
402
403 int main(int argc, char *argv[]) {
404 extern char *optarg;
405 extern int optind, optopt;
406 int opt,rc=0;
407
408 /* logfile NULL means logging to syslog */
409 FILE *lcmaps_logfile=NULL,*lcas_logfile=NULL;
410 int do_lcas=0,do_lcmaps=0,verbose=1;
411 char *pemstring=NULL,*rsl=NULL;
412
413 /* Parse the commandline options */
414 while ((opt = getopt(argc, argv, ":hsqp:x:V:C:l:L:")) != -1) {
415 switch (opt) {
416 case 'h':
417 usage(argv[0]);
418 case 's': /* Do not log to file but to stderr */
419 if (lcmaps_logfile && lcmaps_logfile!=stderr)
420 fclose(lcmaps_logfile);
421 if (lcas_logfile && lcas_logfile!=stderr)
422 fclose(lcas_logfile);
423 lcmaps_logfile=lcas_logfile=stderr;
424 break;
425 case 'q':
426 verbose=0;
427 break;
428 case 'p':
429 pemstring=readproxy(optarg);
430 break;
431 case 'x':
432 setenv("X509_USER_PROXY",optarg,1);
433 break;
434 case 'V':
435 setenv("X509_VOMS_DIR",optarg,1);
436 break;
437 case 'C':
438 setenv("X509_CERT_DIR",optarg,1);
439 break;
440 case 'l':
441 do_lcmaps=1;
442 lcmaps_set_vars(optarg,&lcmaps_logfile);
443 if (optarg[0]=='-') optind--;
444 break;
445 case 'L':
446 do_lcas=1;
447 lcas_set_vars(optarg,&rsl,&lcas_logfile);
448 if (optarg[0]=='-') optind--;
449 break;
450 case ':':
451 /* Option did not receive an expected argument (only when last
452 * of line get here, otherwise next option is used as argument),
453 * includes those with optional arguments, i.e. -l and -L */
454 switch(optopt) {
455 case 'l':
456 do_lcmaps=1;
457 break;
458 case 'L':
459 do_lcas=1;
460 break;
461 default:
462 fprintf(stderr,"%s: option requires an argument -- '%c'\n",
463 argv[0],optopt);
464 fprintf(stderr,"Try `%s -h` for more information.\n",argv[0]);
465 exit(1);
466 }
467 break;
468 case '?':
469 fprintf(stderr,"%s: invalid option -- '%c'\n", argv[0], optopt);
470 fprintf(stderr,"Try `%s -h` for more information.\n",argv[0]);
471 exit(1);
472 }
473 }
474
475 /* Check if we have something to do... */
476 if (do_lcas==0 && do_lcmaps==0) {
477 printf("Nothing to do, see %s -h for valid options.\n",argv[0]);
478 return 0;
479 }
480
481 /* Print warnings when verbose */
482 if (verbose) {
483 if (pemstring==NULL)
484 fprintf(stderr,"Warning: Empty pemstring for proxy.\n");
485 if (getenv("X509_USER_PROXY")==NULL)
486 fprintf(stderr,"Warning: X509_USER_PROXY is not set.\n");
487 if (do_lcas) {
488 if (lcas_logfile==NULL)
489 fprintf(stderr,"Warning: LCAS logging will go to syslog.\n");
490 if (getenv("LCAS_DB_FILE")==NULL)
491 fprintf(stderr,"Warning: using LCAS default db file.\n");
492 }
493 if (do_lcmaps) {
494 if (lcmaps_logfile==NULL)
495 fprintf(stderr,"Warning: LCMAPS logging will go to syslog.\n");
496 if (getenv("LCMAPS_DB_FILE")==NULL)
497 fprintf(stderr,"Warning: using LCMAPS default db file.\n");
498 if (getenv("LCMAPS_POLICY_NAME")==NULL)
499 fprintf(stderr,"Warning: using LCMAPS default policy name.\n");
500 }
501 }
502
503 /* Do LCAS when requested */
504 if (do_lcas) {
505 rc=lcas(pemstring,lcas_logfile,rsl);
506 if (rc!=0) fprintf(stderr,"LCAS failed.\n");
507 }
508
509 /* Do LCMAPS when requested */
510 if (do_lcmaps) {
511 rc=lcmaps(pemstring,lcmaps_logfile);
512 if (rc!=0) fprintf(stderr,"LCMAPS failed.\n");
513 }
514
515 return rc;
516 }

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28