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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2430 - (show annotations) (download) (as text)
Thu Sep 22 10:24:13 2011 UTC (10 years, 3 months ago) by msalle
File MIME type: text/x-chdr
File size: 32659 byte(s)
Remove extra lcmaps_term calls (already called by the lcmaps_return_*
functions). Add explicit call of va_end. Add (commented-out) calls to setvbuf to
change to unbuffered output.


1 /*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 *
14 * Authors: Mischa Sall\'e, Dennis van Dok, Oscar Koeroo
15 * NIKHEF Amsterdam, the Netherlands
16 * <grid-mw-security@nikhef.nl>
17 */
18
19 /*
20 * Command line interface program to interact with LCAS and LCMAPS, e.g. to
21 * follow from userspace the steps gLExec takes. Compile with e.g.
22 * gcc -ldl -rdynamic -o llrun llrun.c
23 * or
24 * gcc -ldl -L. -lvomsfix -o llrun llrun.c
25 * to solve a missing symbol problem with libvomsapi / liblcmaps. The first
26 * version uses the functions defined inside this file, the second gets them
27 * from the dummy library libvomsfix.so
28 */
29
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33
34 #include <string.h>
35 #include <errno.h>
36
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41
42 #include <pwd.h>
43 #include <grp.h>
44
45 #include <dlfcn.h>
46
47 #include <syslog.h>
48
49 #define VERSION "0.1.2"
50
51 /* Define to have getopt() behave POSIX correctly */
52 #define POSIXLY_CORRECT
53
54 /* Dirty hack to fix the missing functions from VOMS API: VOMS API should have
55 * defined these extern "C". LCMAPS needs these functions, and if not using the
56 * ones from LCAS, you can use these (trivial ones) instead. By compiling with
57 * -rdynamic i.e. by linking with -export-dynamic, the following symbols are
58 * used instead. */
59 int getMajorVersionNumber(void) { return 0; }
60 int getPatchVersionNumber(void) { return 0; }
61 int getMinorVersionNumber(void) { return 0; }
62
63 /************************************************************************/
64 /* TYPEDEFS */
65 /************************************************************************/
66
67 /* Global options */
68 typedef struct {
69 int verbose; /* Whether to print extra warnings */
70 int do_lcas; /* Whether to do LCAS */
71 int do_lcmaps; /* Whether to run LCMAPS */
72 char *syslog_fac; /* which syslog facility to use */
73 } opts_t;
74
75 /* Credentials */
76 typedef struct {
77 char *pemstring; /* Will contain a full pemstring */
78 char *dn; /* Will contain a DN */
79 int nfqan; /* Number of specified FQANs */
80 char **fqans; /* Specified FQANs */
81 } cred_t;
82
83 /* lcas_request_t is defined in lcas_types.h, can just re-typedef it here. */
84 #if 0
85 /*#include "lcas_types.h"*/
86 #else
87 typedef char *lcas_request_t;
88 #endif
89
90 /* lcmaps_account_info_t is defined in lcmaps_account.h,
91 * can just re-typedef it here. */
92 #if 0
93 #include "lcmaps_account.h"
94 #else
95 typedef struct lcmaps_account_info_s
96 {
97 uid_t uid; /* the uid of the local account */
98 gid_t * pgid_list; /* the list of primary gids */
99 int npgid; /* the number of primary gids found */
100 gid_t * sgid_list; /* the list of secondary gids */
101 int nsgid; /* the number of secondary gids found */
102 char * poolindex; /* the pool index */
103 } lcmaps_account_info_t;
104 #endif
105
106 /* LCMAPS mode type: determines the LCMAPS interface to be used */
107 typedef enum {
108 LCMAPS_RETURN_ACCOUNT_FROM_PEM,
109 LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI,
110 LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI,
111 } lcmaps_mode_t;
112
113
114 /* Struct containing all the lcmaps related variables, handles and functions,
115 * will be filled using dlsym() */
116 /* List extended with Without-GSI specific functions */
117 typedef struct {
118 /* Variables */
119 int new; /* new API */
120 int dovoms; /* whether to run voms */
121 lcmaps_mode_t mode; /* type of LCMAPS mode */
122 FILE *logfile; /* logfile or NULL for stdout */
123 opts_t *opts; /* global credentials */
124 cred_t *cred; /* global credentials */
125 lcmaps_account_info_t account; /* resulting account info */
126 /* Library handles */
127 void *handle,*helper; /* Needed for dlclose() */
128 /* Functions */
129 int (*lcmaps_init)(FILE*);
130 int (*lcmaps_account_info_init)(lcmaps_account_info_t*);
131 int (*lcmaps_return_account_from_pem)(char*,int,lcmaps_account_info_t*);
132 int (*lcmaps_return_poolindex_without_gsi)(char*,char**,int,
133 lcmaps_account_info_t*);
134 /* int (*lcmaps_return_poolindex_with_mapcounter)(char*,char**,int,int,
135 lcmaps_account_info_t); */
136 int (*lcmaps_return_account_without_gsi)(char*,char**,int,int,
137 lcmaps_account_info_t*);
138 int (*lcmaps_term)(void);
139 int (*lcmaps_account_info_clean)(lcmaps_account_info_t*);
140 int (*lcmaps_get_major_version)(void);
141 int (*lcmaps_get_minor_version)(void);
142 int (*lcmaps_get_patch_version)(void);
143 void (*lcmaps_disable_voms_attributes_verification)(void);
144 void (*lcmaps_enable_voms_attributes_verification)(void);
145 int (*lcmaps_is_set_to_verify_voms_attributes)(void);
146 } lcmaps_t;
147
148
149 /* Struct containing all the lcas functions, will be filled using dlsym() */
150 typedef struct {
151 /* Variables */
152 char *rsl;
153 FILE *logfile; /* logfile or NULL for stdout */
154 opts_t *opts; /* global credentials */
155 cred_t *cred; /* global credentials */
156 /* Library handles */
157 void *handle; /* Needed for dlclose() */
158 /* Functions */
159 int (*lcas_init)(FILE*);
160 int (*lcas_pem)(char*,lcas_request_t);
161 int (*lcas_term)(void);
162 } lcas_t;
163
164
165 /************************************************************************/
166 /* GLOBAL VARIABLE */
167 /************************************************************************/
168
169 /* Short program name, set in main() */
170 static const char *prog=NULL;
171
172
173 /************************************************************************/
174 /* FUNCTIONS */
175 /************************************************************************/
176
177 /* Prints a notice on stdout */
178 void llnotice(char *format, ...) {
179 va_list args;
180
181 fprintf(stdout,"[%s]: ", prog);
182 va_start(args,format);
183 vfprintf(stdout,format,args);
184 va_end(args);
185 }
186
187 /* Prints a warning on stderr */
188 void llwarn(char *format, ...) {
189 va_list args;
190
191 fprintf(stderr,"[%s]: WARNING: ", prog);
192 va_start(args,format);
193 vfprintf(stderr,format,args);
194 va_end(args);
195 }
196
197 /* Prints an error on stderr */
198 void llerr(char *format, ...) {
199 va_list args;
200
201 fprintf(stderr,"[%s]: ERROR: ", prog);
202 va_start(args,format);
203 vfprintf(stderr,format,args);
204 va_end(args);
205 }
206
207 /* Opens the correct syslog facility. Note that the actual opening does not
208 * happen until the first message is logged, see openlog(3)
209 * Return syslog_fac or -1 on error */
210 int opensyslog(const char *name) {
211 int syslog_fac=-1;
212
213 /* Now go over all the possibilities */
214 if (strcmp(name,"LOG_KERN")==0)
215 syslog_fac=LOG_KERN;
216 else if (strcmp(name,"LOG_USER")==0)
217 syslog_fac=LOG_USER;
218 else if (strcmp(name,"LOG_MAIL")==0)
219 syslog_fac=LOG_MAIL;
220 else if (strcmp(name,"LOG_NEWS")==0)
221 syslog_fac=LOG_NEWS;
222 else if (strcmp(name,"LOG_UUCP")==0)
223 syslog_fac=LOG_UUCP;
224 else if (strcmp(name,"LOG_DAEMON")==0)
225 syslog_fac=LOG_DAEMON;
226 else if (strcmp(name,"LOG_AUTH")==0)
227 syslog_fac=LOG_AUTH;
228 else if (strcmp(name,"LOG_CRON")==0)
229 syslog_fac=LOG_CRON;
230 else if (strcmp(name,"LOG_LPR")==0)
231 syslog_fac=LOG_LPR;
232 else if (strcmp(name,"LOG_LOCAL0")==0)
233 syslog_fac=LOG_LOCAL0;
234 else if (strcmp(name,"LOG_LOCAL1")==0)
235 syslog_fac=LOG_LOCAL1;
236 else if (strcmp(name,"LOG_LOCAL2")==0)
237 syslog_fac=LOG_LOCAL2;
238 else if (strcmp(name,"LOG_LOCAL3")==0)
239 syslog_fac=LOG_LOCAL3;
240 else if (strcmp(name,"LOG_LOCAL4")==0)
241 syslog_fac=LOG_LOCAL4;
242 else if (strcmp(name,"LOG_LOCAL5")==0)
243 syslog_fac=LOG_LOCAL5;
244 else if (strcmp(name,"LOG_LOCAL6")==0)
245 syslog_fac=LOG_LOCAL6;
246 else if (strcmp(name,"LOG_LOCAL7")==0)
247 syslog_fac=LOG_LOCAL7;
248 /* Now the non-standard ones... */
249 #ifdef LOG_SYSLOG
250 else if (strcmp(name,"LOG_SYSLOG")==0)
251 syslog_fac=LOG_SYSLOG;
252 #endif
253 #ifdef LOG_FTP
254 else if (strcmp(name,"LOG_FTP")==0)
255 syslog_fac=LOG_FTP;
256 #endif
257 #ifdef LOG_AUTHPRIV
258 else if (strcmp(name,"LOG_AUTHPRIV")==0)
259 syslog_fac=LOG_AUTHPRIV;
260 #endif
261 #ifdef LOG_AUDIT
262 else if (strcmp(name,"LOG_AUDIT")==0)
263 syslog_fac=LOG_AUDIT;
264 #endif
265
266 /* Is it valid? */
267 if (syslog_fac==-1)
268 llerr("Unknown syslog facility '%s' specified.\n",name);
269 else
270 openlog(prog,(LOG_CONS|LOG_PID),syslog_fac);
271
272 return syslog_fac;
273 }
274
275 /* Reads in user proxy (on which mapping is based) from filename or NULL on
276 * error */
277 char *readproxy(const char *filename) {
278 int fd,size;
279 char *pemstring;
280 struct stat st;
281
282 /* Open file and get size */
283 if ((fd=open(filename,O_RDONLY))==-1 || fstat(fd,&st)==-1) {
284 llerr("Cannot open or stat file %s: %s\n", filename, strerror(errno));
285 return NULL;
286 }
287
288 /* Reserve memory */
289 if ((pemstring=(char *)malloc((size_t)(st.st_size+sizeof(char))))==NULL) {
290 llerr("Cannot malloc %d bytes for pemstring\n", (int)st.st_size);
291 return NULL;
292 }
293
294 /* Read file */
295 size=read(fd,pemstring,(size_t)st.st_size);
296 if (size!=st.st_size) {
297 llerr("Number of bytes read %d != size %d\n", size,(int)st.st_size);
298 return NULL;
299 }
300
301 /* Close file */
302 close(fd);
303 /* Add '\0' and return */
304 pemstring[size]='\0';
305
306 return pemstring;
307 }
308
309 /************************************************************************/
310 /* LCMAPS FUNCTIONS */
311 /************************************************************************/
312
313 /* Parses the options for LCMAPS and opens the logfile when needed */
314 int lcmaps_set_vars(char *options, lcmaps_t *lcmaps) {
315 char *var=options,*value,*end,*pos;
316
317 /* Set defaults */
318 lcmaps->new=0; /* assume old when unspecified */
319 lcmaps->dovoms=-1; /* unspecified */
320 lcmaps->mode=LCMAPS_RETURN_ACCOUNT_FROM_PEM;
321
322 /* If first char of options is a - it's actually the next main option */
323 if (options==NULL || options[0]=='-')
324 return 0;
325
326 do {
327 /* Find end of current var=value pair */
328 end=strchr(var, ',');
329 if (end!=NULL) end[0]='\0';
330 /* Find end of variable name */
331 pos=strchr(var,'=');
332 if (pos==NULL)
333 llwarn("Unrecognized element '%s'\n",var);
334 else {
335 pos[0]='\0';
336 value=pos+1;
337 /* Find the variable */
338 if (strcmp(var,"debug")==0)
339 setenv("LCMAPS_DEBUG_LEVEL",value,1);
340 else if (strcmp(var,"policy")==0)
341 setenv("LCMAPS_POLICY_NAME",value,1);
342 else if (strcmp(var,"db")==0)
343 setenv("LCMAPS_DB_FILE",value,1);
344 else if (strcmp(var,"file")==0) {
345 /* Only open when not already linked to stderr */
346 if (lcmaps->logfile==NULL) {
347 if ( (lcmaps->logfile=fopen(value,"a"))==NULL)
348 llwarn("Cannot open %s: %s\n", value,strerror(errno));
349 }
350 } else if (strcmp(var,"mode")==0) {
351 if (strcmp(value, "pem") == 0) {
352 lcmaps->mode = LCMAPS_RETURN_ACCOUNT_FROM_PEM;
353 } else if (strcmp(value, "nogsi_pi") == 0) {
354 lcmaps->mode = LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI;
355 } else if (strcmp(value, "nogsi_ga") == 0) {
356 lcmaps->mode = LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI;
357 } else {
358 llerr("LCMAPS mode should be pem, nogsi_pi or nogsi_ga.\n");
359 return 1;
360 }
361 } else if (strcmp(var,"voms")==0) {
362 if (strcmp(value, "0")==0) {
363 lcmaps->dovoms=0;
364 } else if (strcmp(value, "1") == 0) {
365 lcmaps->dovoms=1;
366 } else {
367 llerr("Invalid value %s for option voms.\n", value);
368 return 1;
369 }
370 } else
371 llwarn("Unrecognized option '%s'\n",var);
372 /* reset value at pos */
373 pos[0]='=';
374 }
375 if (end!=NULL) {
376 /* reset value at end */
377 end[0]=',';
378 /* advance to next option */
379 var=end+1;
380 }
381 } while (end!=NULL);
382 return 0;
383 }
384
385 /* Prints contents of account */
386 void lcmaps_print_account(lcmaps_account_info_t* account) {
387 int i;
388 struct passwd *pw;
389 struct group *gr;
390
391 /* Check if there is anything */
392 if (account->uid==-1) {
393 llnotice("Account info is empty.\n");
394 return;
395 }
396 /* UID / username */
397 pw=getpwuid(account->uid);
398 llnotice("uid=%d(%s)\n",account->uid,pw ? pw->pw_name : "undefined");
399 /* Primary groups */
400 llnotice("primary gids: %d\n",account->npgid);
401 for (i=0; i<account->npgid; i++) {
402 gr=getgrgid(account->pgid_list[i]);
403 llnotice("pgid[%d]=%d(%s)\n",i,
404 account->pgid_list[i],
405 gr ? gr->gr_name : "undefined");
406 }
407 /* Secondary groups */
408 llnotice("secondary gids: %d\n",account->nsgid);
409 for (i=0; i<account->nsgid; i++) {
410 gr=getgrgid(account->sgid_list[i]);
411 llnotice("sgid[%d]=%d(%s)\n",i,
412 account->sgid_list[i],
413 gr ? gr->gr_name : "undefined");
414 }
415 /* Poolindex */
416 llnotice("poolindex=%s\n",
417 (account->poolindex)!=NULL ? account->poolindex : "undefined");
418 }
419
420 /* Dynamically loads LCMAPS library */
421 int lcmaps_loadlib(lcmaps_t *lcmaps,opts_t *opts) {
422 const char *libname;
423
424 switch (lcmaps->mode) {
425 case LCMAPS_RETURN_ACCOUNT_FROM_PEM:
426 libname="liblcmaps_return_account_from_pem.so";
427 break;
428 case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI:
429 libname="liblcmaps_return_poolindex_without_gsi.so";
430 break;
431 case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI:
432 libname="liblcmaps_return_poolindex_without_gsi.so";
433 break;
434 default:
435 llerr("Unknown LCMAPS mode.\n");
436 return 1;
437 }
438
439 /* Make sure lib->handle has welldefined value */
440 lcmaps->handle=lcmaps->helper=NULL;
441
442 /* Load the library lazily: this allows checking for missing symbols */
443 if ( (lcmaps->handle=dlopen(libname, RTLD_LAZY | RTLD_GLOBAL))==NULL ) {
444 llerr("Cannot open LCMAPS lib: %s\n", dlerror());
445 return 1;
446 }
447
448 /* Clear dlerror() */
449 dlerror();
450
451 /* See if we have lcmaps_get*version() functions */
452 lcmaps->lcmaps_get_major_version=
453 (int(*)(void))dlsym(lcmaps->handle,"lcmaps_get_major_version");
454 if (dlerror()==NULL) /* New LCMAPS: no need for get*VersionNumber() */
455 lcmaps->new=1;
456 else { /* Old LCMAPS version */
457 lcmaps->new=0;
458 if (opts->verbose)
459 llwarn("Old LCMAPS version, "\
460 "need to provide missing get*VersionNumber() functions.\n");
461
462 /* Load global symbols, in order to look for getMajorVersionNumber */
463 if ((lcmaps->helper=dlopen(NULL,RTLD_NOW | RTLD_GLOBAL))==NULL) {
464 llerr("Cannot load global symbols: %s\n",dlerror());
465 return 1;
466 }
467
468 /* Now look for getMajorVersionNumber: first look in global symbols, if
469 * not there, try loading vomsfix library, if that fails too, load lcas
470 * instead. */
471 dlsym(lcmaps->helper,"getMajorVersionNumber");
472 if (dlerror()!=NULL) { /* Not in global: try vomsfix lib */
473 dlclose(lcmaps->helper); /* No longer needed, doesn't provide...*/
474 if (opts->verbose)
475 llwarn("trying libvomsfix.so for missing "\
476 "get*VersionNumber() functions.\n");
477 if ( (lcmaps->helper=
478 dlopen("libvomsfix.so",RTLD_NOW | RTLD_GLOBAL))==NULL ) {
479 /* libvomsfix.so doesn't exist or isn't found. Now use lcas as
480 * a backup */
481 if (opts->verbose)
482 llwarn("loading LCAS to provide missing "\
483 "get*VersionNumber() functions.\n");
484 if ( (lcmaps->helper=
485 dlopen("liblcas.so",RTLD_NOW | RTLD_GLOBAL))==NULL) {
486 llerr("%s\n",dlerror());
487 return 1;
488 }
489 }
490 }
491 }
492
493 /* Reopening lcmaps with RTLD_NOW to force loading of secondary dependencies
494 * (e.g. VOMSAPI) */
495 if (dlclose(lcmaps->handle)) {
496 llerr("Cannot close LCMAPS lib: %s\n",dlerror());
497 return 1;
498 }
499 if ( (lcmaps->handle=dlopen(libname, RTLD_NOW | RTLD_GLOBAL))==NULL ) {
500 llerr("%s\n",dlerror());
501 return 1;
502 }
503
504 return 0;
505 }
506
507 /* Dynamically loads LCMAPS library symbols */
508 int lcmaps_loadfcies(lcmaps_t *lcmaps) {
509 char *err;
510
511 /* Load functions */
512 lcmaps->lcmaps_init=(int (*)(FILE*))
513 dlsym(lcmaps->handle,"lcmaps_init");
514 if ( (err=dlerror())!=NULL)
515 goto lcmapsfcies_failed;
516 lcmaps->lcmaps_account_info_init=(int (*)(lcmaps_account_info_t*))
517 dlsym(lcmaps->handle,"lcmaps_account_info_init");
518 if ( (err=dlerror())!=NULL)
519 goto lcmapsfcies_failed;
520 lcmaps->lcmaps_term= (int (*)(void))
521 dlsym(lcmaps->handle,"lcmaps_term");
522 if ( (err=dlerror())!=NULL)
523 goto lcmapsfcies_failed;
524 lcmaps->lcmaps_account_info_clean=(int (*)(lcmaps_account_info_t*))
525 dlsym(lcmaps->handle,"lcmaps_account_info_clean");
526 if ( (err=dlerror())!=NULL)
527 goto lcmapsfcies_failed;
528
529 /* Load LCMAPS runmode specific function (account mapping function) */
530 switch (lcmaps->mode) {
531 case LCMAPS_RETURN_ACCOUNT_FROM_PEM:
532 lcmaps->lcmaps_return_account_from_pem=
533 (int (*)(char*,int,lcmaps_account_info_t*))
534 dlsym(lcmaps->handle,"lcmaps_return_account_from_pem");
535 if ( (err=dlerror())!=NULL)
536 goto lcmapsfcies_failed;
537 break;
538 case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI:
539 lcmaps->lcmaps_return_poolindex_without_gsi=
540 (int (*)(char*,char**,int,lcmaps_account_info_t*))
541 dlsym(lcmaps->handle,"lcmaps_return_poolindex_without_gsi");
542 if ( (err=dlerror())!=NULL)
543 goto lcmapsfcies_failed;
544 break;
545 case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI:
546 lcmaps->lcmaps_return_account_without_gsi=
547 (int (*)(char*,char**,int,int,lcmaps_account_info_t*))
548 dlsym(lcmaps->handle,"lcmaps_return_account_without_gsi");
549 if ( (err=dlerror())!=NULL)
550 goto lcmapsfcies_failed;
551 break;
552 }
553
554 /* When we specified to either enable or disable VOMS, load both symbols */
555 if (lcmaps->dovoms!=-1) {
556 lcmaps->lcmaps_enable_voms_attributes_verification=
557 (void (*)(void))
558 dlsym(lcmaps->handle,
559 "lcmaps_enable_voms_attributes_verification");
560 if ( (err=dlerror())!=NULL) {
561 llerr("Requested API call for disabling voms is not present in "
562 "this LCMAPS.\n");
563 goto lcmapsfcies_failed;
564 }
565 lcmaps->lcmaps_disable_voms_attributes_verification=
566 (void (*)(void))
567 dlsym(lcmaps->handle,
568 "lcmaps_disable_voms_attributes_verification");
569 if ( (err=dlerror())!=NULL) {
570 llerr("Requested API call for disabling voms is not present in "
571 "this LCMAPS.\n");
572 goto lcmapsfcies_failed;
573 }
574 }
575
576 return 0;
577
578 lcmapsfcies_failed:
579 llerr("%s\n",err);
580 dlclose(lcmaps->handle);
581 if (lcmaps->helper)
582 dlclose(lcmaps->helper);
583 return 1;
584 }
585
586 /* Does an lcmaps run, for given credentials and to logfile or syslog when
587 * logfile is NULL. */
588 int lcmaps_run(lcmaps_t *lcmaps) {
589 int rc=0,rc2=0;
590
591 /* init lcmaps */
592 if ( (rc=lcmaps->lcmaps_init(lcmaps->logfile)) ) {
593 llerr("lcmaps_init() failed\n");
594 goto lcmapsrun_closelib;
595 }
596 /* init lcmaps account struct */
597 if ( (rc=lcmaps->lcmaps_account_info_init(&lcmaps->account)) ) {
598 llerr("lcmaps_account_info_init() failed.\n");
599 goto lcmapsrun_closelib;
600 }
601
602 /* Optionally enable/disable voms checking */
603 if (lcmaps->dovoms==0)
604 lcmaps->lcmaps_disable_voms_attributes_verification();
605 else if (lcmaps->dovoms==1)
606 lcmaps->lcmaps_enable_voms_attributes_verification();
607
608 /* Do actual mapping call. NOTE: this also calls lcmaps_term() */
609 switch (lcmaps->mode) {
610 case LCMAPS_RETURN_ACCOUNT_FROM_PEM:
611 if ( (rc=lcmaps->lcmaps_return_account_from_pem(
612 lcmaps->cred->pemstring,-1,&lcmaps->account)) ) {
613 llerr("lcmaps_return_account_from_pem() failed.\n");
614 goto lcmapsrun_clean;
615 }
616 break;
617 case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI:
618 if ( (rc=lcmaps->lcmaps_return_poolindex_without_gsi(
619 lcmaps->cred->dn, lcmaps->cred->fqans,
620 lcmaps->cred->nfqan, &lcmaps->account)) ) {
621 llerr("lcmaps_return_poolindex_without_gsi() failed.\n");
622 goto lcmapsrun_clean;
623 }
624 break;
625 case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI:
626 if ( (rc=lcmaps->lcmaps_return_account_without_gsi(
627 lcmaps->cred->dn, lcmaps->cred->fqans,
628 lcmaps->cred->nfqan, 0, &lcmaps->account)) ) {
629 llerr("lcmaps_return_account_without_gsi() failed.\n");
630 goto lcmapsrun_clean;
631 }
632 break;
633 }
634 /* LCMAPS finished succesfully */
635 rc=0;
636 llnotice("LCMAPS succeeded.\n");
637
638 /* Print contents of account */
639 lcmaps_print_account(&lcmaps->account);
640
641 lcmapsrun_clean:
642 /* Cleaning and freeing the account structure */
643 if ( (rc2=lcmaps->lcmaps_account_info_clean(&lcmaps->account)) )
644 llerr("lcmaps_account_info_clean() failed.\n");
645
646 lcmapsrun_closelib:
647 /* Close library */
648 dlclose(lcmaps->handle);
649 if (lcmaps->helper)
650 dlclose(lcmaps->helper);
651 /* when non-clean function failed: return its rc, otherwise that of clean */
652 return (rc ? rc : rc2);
653 }
654
655 /************************************************************************/
656 /* LCAS FUNCTIONS */
657 /************************************************************************/
658
659 /* Parses the options for LCAS and opens the logfile when needed */
660 int lcas_set_vars(char *options,lcas_t *lcas) {
661 char *var=options,*value,*end,*pos;
662
663 /* set defaults */
664 lcas->rsl=NULL;
665
666 /* If first char of options is a - it's actually the next main option */
667 if (options==NULL || options[0]=='-')
668 return 0;
669
670 do {
671 /* Find end of current var=value pair */
672 end=strchr(var, ',');
673 if (end!=NULL) end[0]='\0';
674 /* Find end of variable name */
675 pos=strchr(var,'=');
676 if (pos==NULL)
677 llerr("Unrecognized element '%s'\n", var);
678 else {
679 pos[0]='\0';
680 value=pos+1;
681 /* Find the variable */
682 if (strcmp(var,"debug")==0)
683 setenv("LCAS_DEBUG_LEVEL",value,1);
684 else if (strcmp(var,"db")==0)
685 setenv("LCAS_DB_FILE",value,1);
686 else if (strcmp(var,"rsl")==0) {
687 if ((lcas->rsl=strdup(value))==NULL) {
688 llerr("Cannot strdup() RSL string for LCAS\n");
689 return 1;
690 }
691 }
692 else if (strcmp(var,"file")==0) {
693 /* Only open when not already linked to stderr */
694 if (lcas->logfile==NULL) {
695 if ( (lcas->logfile=fopen(value,"a"))==NULL)
696 llwarn("Cannot open %s: %s\n", value,strerror(errno));
697 }
698 }
699 else
700 llwarn("Unrecognized option '%s'\n",var);
701 /* reset value at pos */
702 pos[0]='=';
703 }
704 if (end!=NULL) {
705 /* reset value at end */
706 end[0]=',';
707 /* advance to next option */
708 var=end+1;
709 }
710 } while (end!=NULL);
711
712 return 0;
713 }
714
715 /* Dynamically loads LCAS library and all needed symbols */
716 int lcas_loadlib(lcas_t *lcas,opts_t *flags) {
717 /* Load the library */
718 if ( (lcas->handle=
719 dlopen("liblcas.so",RTLD_NOW | RTLD_GLOBAL))==NULL ) {
720 llerr("%s\n",dlerror());
721 return 1;
722 }
723 return 0;
724 }
725
726 /* Dynamically loads LCAS library symbols */
727 int lcas_loadfcies(lcas_t *lcas) {
728 char *err;
729
730 /* Clean dlerror() */
731 dlerror();
732
733 /* Load functions */
734 lcas->lcas_init=(int (*)(FILE*))
735 dlsym(lcas->handle,"lcas_init");
736 if ( (err=dlerror())!=NULL)
737 goto lcasfcies_failed;
738 lcas->lcas_pem= (int (*)(char*,lcas_request_t))
739 dlsym(lcas->handle,"lcas_pem");
740 if ( (err=dlerror())!=NULL)
741 goto lcasfcies_failed;
742 lcas->lcas_term=(int (*)(void))
743 dlsym(lcas->handle,"lcas_term");
744 if ( (err=dlerror())!=NULL)
745 goto lcasfcies_failed;
746
747 return 0;
748
749 lcasfcies_failed:
750 llerr("%s\n",err);
751 dlclose(lcas->handle);
752 return 1;
753 }
754
755 /* Loads LCAS library and does a run, for given pemstring and to logfile or
756 * syslog when logfile is NULL and given rsl (=cmd + arguments) */
757 int lcas_run(lcas_t *lcas) {
758 int rc;
759
760 /* Do a run */
761 if ((rc=lcas->lcas_init(lcas->logfile))) {
762 llerr("lcas_init() failed\n");
763 goto lcasrun_closelib;
764 }
765 if ((rc=lcas->lcas_pem(lcas->cred->pemstring,(lcas_request_t)(lcas->rsl)))){
766 llerr("lcas_pem() failed.\n");
767 goto lcasrun_closelib;
768 }
769 if ( (rc=lcas->lcas_term()) ) {
770 llerr("lcas_term() failed.\n");
771 goto lcasrun_closelib;
772 }
773 llnotice("LCAS succeeded.\n");
774
775 lcasrun_closelib:
776 /* Close library */
777 dlclose(lcas->handle);
778
779 return rc;
780 }
781
782 /* Print the version */
783 void version(void) {
784 printf("%s version: %s\n",prog,VERSION);
785 exit (0);
786 }
787
788 /* Prints out usage information */
789 void usage(void) {
790 int uid=(int)getuid();
791
792 printf("Usage: %s [options]\n\n",prog);
793 printf("Valid options are:\n"
794 " -h print this help text.\n"
795 " -v print version.\n\n"
796 " -s send output to stderr instead of syslog or file.\n"
797 " -S<facility> use specified syslog facility in case of logging "
798 "to syslog.\n"
799 " -q quiet output (no warnings).\n"
800 " -p<file> read pemstring from given file.\n"
801 " -x<file> set or override X509_USER_PROXY to given file.\n\n"
802 " -V<dir> set or override X509_VOMS_DIR to given dir.\n"
803 " -C<dir> set or override X509_CERT_DIR to given dir.\n\n"
804 " -L[opts] run LCAS with given options: "
805 "<var>=<value>,<var=value>,...\n"
806 " db=<file> set or override LCAS_DB_FILE.\n"
807 " debug=<level> set or override LCAS_DEBUG_LEVEL.\n"
808 " rsl=<string> set rsl string (needs to be quoted).\n"
809 " file=<file> send debug/log output to file instead of "
810 "syslog, ignored\n when -s is specified.\n"
811 "\n -l[opts] run LCMAPS with given options: "
812 "<var>=<value>,<var=value>,...\n"
813 " db=<file> set or override LCMAPS_DB_FILE.\n"
814 " policy=<name> set or override LCMAPS_POLICY_NAME.\n"
815 " debug=<level> set or override LCMAPS_DEBUG_LEVEL.\n"
816 " file=<file> send debug/log output to file instead of "
817 "syslog, ignored\n when -s is specified.\n"
818 " voms={0,1} disable/enable VOMS verification.\n"
819 " mode=<mode> LCMAPS normally extracts all information from "
820 "a PEM string\n"
821 " (i.e. a proxy certificate), but it can be run "
822 "in a mode\n"
823 " \"without_gsi\" where the data such as the DN "
824 "and FQAN are\n"
825 " passed as plain strings, as set on the command "
826 "line.\n"
827 " with -d and -f. Valid modes are:\n"
828 " pem run LCMAPS get_account with pem "
829 "string (default).\n"
830 " nogsi_pi run LCMAPS "
831 "return_poolindex_without_gsi\n"
832 " nogsi_ga run LCMAPS "
833 "return_account_without_gsi\n"
834 " -d<DN> use DN (in without_gsi mode)\n"
835 " -f<FQAN> use FQAN (in without_gsi mode)\n"
836 );
837 printf("\nExample:\n");
838 printf(" %s -s -p/tmp/x509up_u%d -x/tmp/x509up_u%d \\\n",prog,uid,uid);
839 printf(" -L debug=5,db=/tmp/lcas.db \\\n");
840 printf(" -l policy=glexec_get_account,debug=5,db=/tmp/lcmaps.db\n");
841 printf("\nNotes on reproducing gLExec behaviour:\n");
842 printf("- gLExec uses an LCMAPS policy named 'glexec_get_account'\n");
843 printf("- the proxy specified with -p is the analog of the ");
844 printf("GLEXEC_CLIENT_CERT.\n");
845
846 exit(0);
847 }
848
849 /*
850 * Initializes the structs, then fills them based on the cmdline args, finally
851 * does some basic checking of the supplied input.
852 */
853 void parse_options(int argc, char *argv[],
854 cred_t *cred, opts_t *opts,
855 lcmaps_t *lcmaps, lcas_t *lcas) {
856 extern char *optarg;
857 extern int optind, optopt;
858 int opt,i,fqan_idx=0;
859 size_t size;
860 char *dummy;
861
862 /* Get basename, don't rely on basename(3). argv[0] will not contain a
863 * trailing / and will also not be empty... */
864 dummy=strrchr(argv[0],'/');
865 prog=( dummy==NULL ? argv[0] : &(dummy[1]) );
866
867 /* Set other defaults */
868 opts->verbose=1;
869 opts->do_lcas=0;
870 opts->do_lcmaps=0;
871 opts->syslog_fac=NULL;
872
873 cred->nfqan=0;
874 cred->fqans=NULL;
875 cred->pemstring=NULL;
876 cred->dn=NULL;
877
878 lcmaps->logfile=lcas->logfile=NULL;
879
880 /* Look for number of FQAN options such that we can initialize the array */
881 for (i=1; i<argc; i++) {
882 if (strcmp(argv[i],"-f")==0) {
883 cred->nfqan++;
884 i++; /* skip next argument: it's the FQAN */
885 }
886 }
887 /* Malloc memory for them... */
888 if (cred->nfqan>0) {
889 size=sizeof(char*)*(cred->nfqan+1);
890 if ( (cred->fqans=malloc(size))==NULL ) {
891 llerr("Cannot malloc %d bytes for fqans\n",(int)size);
892 exit(1);
893 }
894 cred->fqans[cred->nfqan]=NULL; /* NULL-terminate list */
895 }
896
897 /* Parse the commandline options */
898 while ((opt = getopt(argc, argv, ":hvsS:qp:x:V:C:l:L:d:f:")) != -1) {
899 switch (opt) {
900 case 'h':
901 usage();
902 case 'v':
903 version();
904 case 's': /* Do not log to file but to stderr */
905 /* Uncomment next lines to use unbuffered output */
906 /* setvbuf(stdout,(char*)NULL,_IONBF,0);
907 setvbuf(stderr,(char*)NULL,_IONBF,0);*/
908 if (lcmaps->logfile && lcmaps->logfile!=stderr)
909 fclose(lcmaps->logfile);
910 if (lcas->logfile && lcas->logfile!=stderr)
911 fclose(lcas->logfile);
912 lcmaps->logfile=lcas->logfile=stderr;
913 break;
914 case 'S':
915 opts->syslog_fac=optarg;
916 if (opensyslog(opts->syslog_fac)==-1)
917 exit(1);
918 break;
919 case 'q':
920 opts->verbose=0;
921 break;
922 case 'p':
923 if ((cred->pemstring=readproxy(optarg))==NULL)
924 exit(1);
925 break;
926 case 'x':
927 setenv("X509_USER_PROXY",optarg,1);
928 break;
929 case 'V':
930 setenv("X509_VOMS_DIR",optarg,1);
931 break;
932 case 'C':
933 setenv("X509_CERT_DIR",optarg,1);
934 break;
935 case 'l':
936 opts->do_lcmaps=lcmaps_set_vars(optarg,lcmaps)==0 ? 1 : 0;
937 if (optarg[0]=='-') optind--;
938 break;
939 case 'L':
940 opts->do_lcas=lcas_set_vars(optarg,lcas)==0 ? 1 : 0;
941 if (optarg[0]=='-') optind--;
942 break;
943 case 'd':
944 cred->dn = optarg;
945 break;
946 case 'f':
947 cred->fqans[fqan_idx++]=optarg;
948 break;
949 case ':':
950 /* Option did not receive an expected argument (only when last
951 * of line get here, otherwise next option is used as argument),
952 * includes those with optional arguments, i.e. -l and -L */
953 switch(optopt) {
954 case 'l':
955 lcmaps_set_vars(NULL,lcmaps);
956 opts->do_lcmaps=1;
957 break;
958 case 'L':
959 lcas_set_vars(NULL,lcas);
960 opts->do_lcas=1;
961 break;
962 default:
963 fprintf(stderr,
964 "%s: option requires an argument -- '%c'\n",
965 prog,optopt);
966 fprintf(stderr,"Try `%s -h` for more information.\n",
967 prog);
968 exit(1);
969 }
970 break;
971 case '?':
972 fprintf(stderr,"%s: invalid option -- '%c'\n", prog, optopt);
973 fprintf(stderr,"Try `%s -h` for more information.\n",prog);
974 exit(1);
975 }
976 }
977
978 /* Print warnings when verbose */
979 if (opts->verbose) {
980 if (cred->pemstring==NULL)
981 llwarn("Empty pemstring for proxy.\n");
982 if (getenv("X509_USER_PROXY")==NULL)
983 llwarn("X509_USER_PROXY is not set.\n");
984 if (opts->do_lcas) {
985 if (lcas->logfile==NULL) {
986 llwarn("LCAS logging will go to syslog");
987 if (opts->syslog_fac==NULL)
988 fprintf(stderr,".\n");
989 else
990 fprintf(stderr,", using facility %s.\n",opts->syslog_fac);
991 }
992 if (getenv("LCAS_DB_FILE")==NULL)
993 llwarn("using LCAS default db file.\n");
994 }
995 if (opts->do_lcmaps) {
996 if (lcmaps->logfile==NULL) {
997 llwarn("LCMAPS logging will go to syslog");
998 if (opts->syslog_fac==NULL)
999 fprintf(stderr,".\n");
1000 else
1001 fprintf(stderr,", using facility %s.\n",opts->syslog_fac);
1002 }
1003 if (getenv("LCMAPS_DB_FILE")==NULL)
1004 llwarn("using LCMAPS default db file.\n");
1005 if (getenv("LCMAPS_POLICY_NAME")==NULL)
1006 llwarn("using LCMAPS default policy name.\n");
1007 if ( (lcmaps->mode == LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI ||
1008 lcmaps->mode == LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI) &&
1009 cred->dn == NULL)
1010 llwarn("running without GSI with NULL DN string.\n");
1011 }
1012 }
1013 }
1014
1015 /************************************************************************/
1016 /* MAIN() FUNCTION */
1017 /************************************************************************/
1018
1019 /* Main() */
1020 int main(int argc, char *argv[]) {
1021 int rc=0;
1022
1023 lcas_t lcas;
1024 lcmaps_t lcmaps;
1025 opts_t opts;
1026 cred_t cred;
1027
1028 /* Initialize LCMAPS and LCAS structs */
1029 lcmaps.opts=lcas.opts=&opts;
1030 lcmaps.cred=lcas.cred=&cred;
1031
1032 /* Parse cmdline input and fill cred, opts and lcmaps/lcas structs */
1033 parse_options(argc,argv,&cred,&opts,&lcmaps,&lcas);
1034
1035 /* Check if we have something to do... */
1036 if (opts.do_lcas==0 && opts.do_lcmaps==0) {
1037 llnotice("Nothing to do, see %s -h for valid options.\n",prog);
1038 return 0;
1039 }
1040
1041 /* Do LCAS when requested */
1042 if (opts.do_lcas) {
1043 rc=(lcas_loadlib(&lcas,&opts) ||
1044 lcas_loadfcies(&lcas) ||
1045 lcas_run(&lcas));
1046 if (rc!=0)
1047 llerr("LCAS failed.\n");
1048 if (lcas.rsl)
1049 free(lcas.rsl);
1050 }
1051
1052 /* Do LCMAPS when requested */
1053 if (opts.do_lcmaps) {
1054 rc=(lcmaps_loadlib(&lcmaps, &opts) ||
1055 lcmaps_loadfcies(&lcmaps) ||
1056 lcmaps_run(&lcmaps));
1057 if (rc!=0)
1058 llerr("LCMAPS failed.\n");
1059 }
1060
1061 free(cred.pemstring);
1062 free(cred.fqans);
1063
1064 return rc;
1065 }

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