/[pdpsoft]/tags/llrun_R_0_1_0_1/llrun.c
ViewVC logotype

Contents of /tags/llrun_R_0_1_0_1/llrun.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2096 - (show annotations) (download) (as text)
Thu Nov 18 15:25:05 2010 UTC (11 years, 2 months ago) by msalle
File MIME type: text/x-chdr
File size: 32562 byte(s)
First official version of llrun (formerly lcaslcmaps_get_account_cli.c).
- able to handle three different LCMAPS interfaces
- compatible with glexec 0.8 (and before)

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

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