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 |
15 |
* NIKHEF Amsterdam, the Netherlands |
16 |
* <grid-mw-security@nikhef.nl> |
17 |
* |
18 |
* |
19 |
* Test program to interact with LCAS and LCMAPS. It can be used to follow from |
20 |
* userspace the steps gLExec takes. |
21 |
* Compile with e.g. |
22 |
* gcc -ldl -rdynamic -o lcaslcmaps_getaccount_cli lcaslcmaps_getaccount_cli.c |
23 |
* or |
24 |
* gcc -ldl -L. -lvomsfix -o lcaslcmaps_getaccount_cli lcaslcmaps_getaccount_cli.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 |
|
31 |
|
32 |
|
33 |
#include <stdio.h> |
34 |
#include <stdlib.h> |
35 |
|
36 |
#include <string.h> |
37 |
#include <errno.h> |
38 |
|
39 |
#include <sys/types.h> |
40 |
#include <sys/stat.h> |
41 |
#include <fcntl.h> |
42 |
#include <unistd.h> |
43 |
|
44 |
#include <pwd.h> |
45 |
#include <grp.h> |
46 |
|
47 |
#include <dlfcn.h> |
48 |
|
49 |
/* Dirty hack to fix the missing functions from VOMS API: VOMS API should have |
50 |
* defined these extern "C". LCMAPS needs these functions, and if not using the |
51 |
* ones from LCAS, you can use these (trivial ones) instead. By compiling with |
52 |
* -rdynamic i.e. by linking with -export-dynamic, the following symbols are |
53 |
* used instead. */ |
54 |
int getMajorVersionNumber(void) { return 0; } |
55 |
int getPatchVersionNumber(void) { return 0; } |
56 |
int getMinorVersionNumber(void) { return 0; } |
57 |
|
58 |
/* lcas_request_t is defined in lcas_types.h, can just re-typedef it here. */ |
59 |
#if 0 |
60 |
/*#include "lcas_types.h"*/ |
61 |
#else |
62 |
typedef char *lcas_request_t; |
63 |
#endif |
64 |
|
65 |
/* lcmaps_account_info_t is defined in lcmaps_account.h, |
66 |
* can just re-typedef it here. */ |
67 |
#if 0 |
68 |
#include "lcmaps_account.h" |
69 |
#else |
70 |
typedef struct lcmaps_account_info_s |
71 |
{ |
72 |
uid_t uid; /* the uid of the local account */ |
73 |
gid_t * pgid_list; /* the list of primary gids */ |
74 |
int npgid; /* the number of primary gids found */ |
75 |
gid_t * sgid_list; /* the list of secondary gids */ |
76 |
int nsgid; /* the number of secondary gids found */ |
77 |
char * poolindex; /* the pool index */ |
78 |
} lcmaps_account_info_t; |
79 |
#endif |
80 |
|
81 |
typedef enum { |
82 |
LCMAPS_RETURN_ACCOUNT_FROM_PEM, |
83 |
LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI, |
84 |
LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI, |
85 |
} lcmaps_mode_t; |
86 |
|
87 |
|
88 |
/* Define to have getopt() behave POSIX correctly */ |
89 |
#define POSIXLY_CORRECT |
90 |
|
91 |
/* Struct containing all the lcmaps functions, will be filled using dlsym() */ |
92 |
/* List extended with Without GSI specific functions */ |
93 |
typedef struct { |
94 |
void *handle,*helper; /* Needed for dlclose() */ |
95 |
int (*lcmaps_init)(FILE*); |
96 |
int (*lcmaps_account_info_init)(lcmaps_account_info_t*); |
97 |
int (*lcmaps_return_account_from_pem)(char*,int,lcmaps_account_info_t*); |
98 |
int (*lcmaps_return_poolindex_without_gsi)(char*,char**,int,lcmaps_account_info_t*); |
99 |
/* int (*lcmaps_return_poolindex_with_mapcounter)(char*,char**,int,int,lcmaps_account_info_t); */ |
100 |
int (*lcmaps_return_account_without_gsi)(char*,char**,int,int,lcmaps_account_info_t*); |
101 |
int (*lcmaps_term)(void); |
102 |
} lcmaps_library_t; |
103 |
|
104 |
|
105 |
|
106 |
/* Struct containing all the lcas functions, will be filled using dlsym() */ |
107 |
typedef struct { |
108 |
void *handle; /* Needed for dlclose() */ |
109 |
int (*lcas_init)(FILE*); |
110 |
int (*lcas_pem)(char*,lcas_request_t); |
111 |
int (*lcas_term)(void); |
112 |
} lcas_library_t; |
113 |
|
114 |
/* Parses the options for LCMAPS and opens the logfile when needed */ |
115 |
int lcmaps_set_vars(char *options,FILE **log) { |
116 |
char *var=options,*value,*end,*pos; |
117 |
|
118 |
/* If first char of options is a - it's actually the next main option */ |
119 |
if (options[0]=='-') |
120 |
return 0; |
121 |
|
122 |
do { |
123 |
/* Find end of current var=value pair */ |
124 |
end=strchr(var, ','); |
125 |
if (end!=NULL) end[0]='\0'; |
126 |
/* Find end of variable name */ |
127 |
pos=strchr(var,'='); |
128 |
if (pos==NULL) |
129 |
fprintf(stderr,"Unrecognized element '%s'\n", var); |
130 |
else { |
131 |
pos[0]='\0'; |
132 |
value=pos+1; |
133 |
/* Find the variable */ |
134 |
if (strcmp(var,"debug")==0) |
135 |
setenv("LCMAPS_DEBUG_LEVEL",value,1); |
136 |
/* else if (strcmp(var,"log")==0) |
137 |
setenv("LCMAPS_LOG_LEVEL",value,1);*/ |
138 |
else if (strcmp(var,"policy")==0) |
139 |
setenv("LCMAPS_POLICY_NAME",value,1); |
140 |
else if (strcmp(var,"db")==0) |
141 |
setenv("LCMAPS_DB_FILE",value,1); |
142 |
else if (strcmp(var,"file")==0) { |
143 |
/* Only open when not already linked to stderr */ |
144 |
if (*log==NULL) { |
145 |
if ( (*log=fopen(value,"a"))==NULL) |
146 |
fprintf(stderr,"Cannot open %s: %s\n", |
147 |
value,strerror(errno)); |
148 |
} |
149 |
} |
150 |
else |
151 |
fprintf(stderr,"Unrecognized option '%s'\n",var); |
152 |
/* reset value at pos */ |
153 |
pos[0]='='; |
154 |
} |
155 |
if (end!=NULL) { |
156 |
/* reset value at end */ |
157 |
end[0]=','; |
158 |
/* advance to next option */ |
159 |
var=end+1; |
160 |
} |
161 |
} while (end!=NULL); |
162 |
return 0; |
163 |
} |
164 |
|
165 |
/* Prints contents of account */ |
166 |
void lcmaps_print_account(lcmaps_account_info_t* account) { |
167 |
int i; |
168 |
struct passwd *pw; |
169 |
struct group *gr; |
170 |
|
171 |
/* Check if there is anything */ |
172 |
if (account->uid==-1) { |
173 |
printf("Account info is empty.\n"); |
174 |
return; |
175 |
} |
176 |
/* UID / username */ |
177 |
pw=getpwuid(account->uid); |
178 |
printf("uid=%d(%s)\n",account->uid,pw ? pw->pw_name : "undefined"); |
179 |
/* Primary groups */ |
180 |
printf("primary gids: %d\n",account->npgid); |
181 |
for (i=0; i<account->npgid; i++) { |
182 |
gr=getgrgid(account->pgid_list[i]); |
183 |
printf("pgid[%d]=%d(%s)\n",i, |
184 |
account->pgid_list[i], |
185 |
gr ? gr->gr_name : "undefined"); |
186 |
} |
187 |
/* Secondary groups */ |
188 |
printf("secondary gids: %d\n",account->nsgid); |
189 |
for (i=0; i<account->nsgid; i++) { |
190 |
gr=getgrgid(account->sgid_list[i]); |
191 |
printf("sgid[%d]=%d(%s)\n",i, |
192 |
account->sgid_list[i], |
193 |
gr ? gr->gr_name : "undefined"); |
194 |
} |
195 |
/* Poolindex */ |
196 |
printf("poolindex=%s\n", |
197 |
(account->poolindex)!=NULL ? account->poolindex : "undefined"); |
198 |
} |
199 |
|
200 |
/* Dynamically loads LCMAPS library and all needed symbols */ |
201 |
int loadlcmaps(lcmaps_library_t *lib, lcmaps_mode_t mode) { |
202 |
/* Make sure lib->handle has welldefined value */ |
203 |
lib->handle=lib->helper=NULL; |
204 |
|
205 |
/* Load global symbols, so that we can search for getMajorVersionNumber */ |
206 |
if ((lib->helper=dlopen(NULL,RTLD_NOW | RTLD_GLOBAL))==NULL) { |
207 |
fprintf(stderr,"Error loading global symbols: %s\n",dlerror()); |
208 |
return 1; |
209 |
} |
210 |
|
211 |
/* Now look for getMajorVersionNumber: first look in global symbols, if not |
212 |
* there, try loading vomsfix library, if that fails too, load lcas instead. |
213 |
* */ |
214 |
if (dlsym(lib->helper,"getMajorVersionNumber")==NULL) { |
215 |
dlclose(lib->helper); /* No longer needed, doesn't provide...*/ |
216 |
fprintf(stderr,"Warning: trying libvomsfix.so for missing get*VersionNumber() functions.\n"); |
217 |
if ((lib->helper=dlopen("libvomsfix.so",RTLD_NOW | RTLD_GLOBAL))==NULL) { |
218 |
/* libvomsfix.so doesn't exist or isn't found. Now use lcas as a |
219 |
* backup */ |
220 |
fprintf(stderr,"Warning: loading LCAS to provide missing get*VersionNumber() functions.\n"); |
221 |
if ((lib->helper=dlopen("liblcas.so",RTLD_NOW | RTLD_GLOBAL))==NULL) { |
222 |
fprintf(stderr,"Error: %s\n",dlerror()); |
223 |
return 1; |
224 |
} |
225 |
} |
226 |
} |
227 |
/* lib->helper now contains the handle containing get*VersionNumber() */ |
228 |
|
229 |
/* Now load the real library */ |
230 |
switch (mode) { |
231 |
case LCMAPS_RETURN_ACCOUNT_FROM_PEM: |
232 |
if ( (lib->handle=dlopen("liblcmaps_return_account_from_pem.so", |
233 |
RTLD_NOW | RTLD_GLOBAL))==NULL ) { |
234 |
fprintf(stderr,"Error: %s\n",dlerror()); |
235 |
return 1; |
236 |
} |
237 |
break; |
238 |
case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI: |
239 |
if ( (lib->handle=dlopen("liblcmaps_return_poolindex_without_gsi.so", |
240 |
RTLD_NOW | RTLD_GLOBAL))==NULL ) { |
241 |
fprintf(stderr,"Error: %s\n",dlerror()); |
242 |
return 1; |
243 |
} |
244 |
break; |
245 |
case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI: |
246 |
/* if ( (lib->handle=dlopen("liblcmaps_without_gsi.so", */ |
247 |
if ( (lib->handle=dlopen("liblcmaps_return_poolindex_without_gsi.so", |
248 |
RTLD_NOW | RTLD_GLOBAL))==NULL ) { |
249 |
fprintf(stderr,"Error: %s\n",dlerror()); |
250 |
return 1; |
251 |
} |
252 |
} |
253 |
|
254 |
#define print_dlerror_and_return { fprintf(stderr,"Error: %s\n",dlerror()); \ |
255 |
dlclose(lib->handle); \ |
256 |
dlclose(lib->helper); \ |
257 |
return 1; } |
258 |
|
259 |
/* Load functions */ |
260 |
if ( (lib->lcmaps_init= |
261 |
(int (*)(FILE*)) dlsym(lib->handle,"lcmaps_init"))==NULL || |
262 |
(lib->lcmaps_account_info_init= |
263 |
(int (*)(lcmaps_account_info_t*)) |
264 |
dlsym(lib->handle,"lcmaps_account_info_init"))==NULL || |
265 |
(lib->lcmaps_term= |
266 |
(int (*)(void)) dlsym(lib->handle,"lcmaps_term"))==NULL ) { |
267 |
fprintf(stderr,"Error: %s\n",dlerror()); |
268 |
dlclose(lib->handle); |
269 |
dlclose(lib->helper); |
270 |
return 1; |
271 |
} |
272 |
|
273 |
switch (mode) { |
274 |
case LCMAPS_RETURN_ACCOUNT_FROM_PEM: |
275 |
if ( (lib->lcmaps_return_account_from_pem= |
276 |
(int (*)(char*,int,lcmaps_account_info_t*)) |
277 |
dlsym(lib->handle,"lcmaps_return_account_from_pem"))==NULL ) { |
278 |
fprintf(stderr,"Error: %s\n",dlerror()); |
279 |
dlclose(lib->handle); |
280 |
dlclose(lib->helper); |
281 |
return 1; |
282 |
} |
283 |
break; |
284 |
case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI: |
285 |
if ( (lib->lcmaps_return_poolindex_without_gsi= |
286 |
(int (*)(char*,char**,int,lcmaps_account_info_t*)) |
287 |
dlsym(lib->handle,"lcmaps_return_poolindex_without_gsi"))==NULL ) |
288 |
print_dlerror_and_return; |
289 |
break; |
290 |
case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI: |
291 |
if ( (lib->lcmaps_return_account_without_gsi= |
292 |
(int (*)(char*,char**,int,int,lcmaps_account_info_t*)) |
293 |
dlsym(lib->handle,"lcmaps_return_account_without_gsi"))==NULL ) |
294 |
print_dlerror_and_return; |
295 |
} |
296 |
|
297 |
|
298 |
return 0; |
299 |
} |
300 |
|
301 |
|
302 |
|
303 |
/* Loads LCMAPS library and does a run, for given pemstring and to logfile or |
304 |
* syslog when logfile is NULL. */ |
305 |
int lcmaps_pem(char *pemstring,FILE *logfile) { |
306 |
int rc; |
307 |
lcmaps_library_t lib; |
308 |
lcmaps_account_info_t account; |
309 |
|
310 |
/* Load lcmaps library and symbols */ |
311 |
if (loadlcmaps(&lib, LCMAPS_RETURN_ACCOUNT_FROM_PEM)) |
312 |
return 1; |
313 |
|
314 |
/* Do a run */ |
315 |
if ( (rc=lib.lcmaps_init(logfile)) ) { |
316 |
fprintf(stderr,"lcmaps_init() failed\n"); |
317 |
goto finalize; |
318 |
} |
319 |
if ( (rc=lib.lcmaps_account_info_init(&account)) ) { |
320 |
fprintf(stderr,"lcmaps_account_info_init() failed.\n"); |
321 |
goto finalize; |
322 |
} |
323 |
if ( (rc=lib.lcmaps_return_account_from_pem(pemstring,-1,&account)) ) { |
324 |
fprintf(stderr,"lcmaps_return_account_from_pem() failed.\n"); |
325 |
goto finalize; |
326 |
} |
327 |
if ( (rc=lib.lcmaps_term()) ) { |
328 |
fprintf(stderr,"lcmaps_term() failed.\n"); |
329 |
goto finalize; |
330 |
} |
331 |
/* LCMAPS finished succesfully */ |
332 |
rc=0; |
333 |
printf("LCMAPS succeeded.\n"); |
334 |
|
335 |
/* Print contents of account */ |
336 |
lcmaps_print_account(&account); |
337 |
|
338 |
finalize: |
339 |
/* Close library */ |
340 |
dlclose(lib.handle); |
341 |
return rc; |
342 |
} |
343 |
|
344 |
int lcmaps_nogsi_pool(char *my_dn, char *fqan, FILE *logfile) { |
345 |
int rc; |
346 |
lcmaps_library_t lib; |
347 |
lcmaps_account_info_t account; |
348 |
|
349 |
char ** fqans = NULL; |
350 |
|
351 |
fqans = malloc(sizeof(char*) * 2); |
352 |
fqans[0] = fqan; |
353 |
|
354 |
/* Load lcmaps library and symbols */ |
355 |
if (loadlcmaps(&lib,LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI)) |
356 |
return 1; |
357 |
|
358 |
/* Do a run */ |
359 |
if ( (rc=lib.lcmaps_init(logfile)) ) { |
360 |
fprintf(stderr,"lcmaps_init() failed\n"); |
361 |
goto finalize; |
362 |
} |
363 |
if ( (rc=lib.lcmaps_account_info_init(&account)) ) { |
364 |
fprintf(stderr,"lcmaps_account_info_init() failed.\n"); |
365 |
goto finalize; |
366 |
} |
367 |
if ( (rc=lib.lcmaps_return_poolindex_without_gsi(my_dn, fqans, 1, &account)) ) { |
368 |
fprintf(stderr,"lib.lcmaps_return_poolindex_without_gsi() failed.\n"); |
369 |
goto finalize; |
370 |
} |
371 |
if ( (rc=lib.lcmaps_term()) ) { |
372 |
fprintf(stderr,"lcmaps_term() failed.\n"); |
373 |
goto finalize; |
374 |
} |
375 |
/* LCMAPS finished succesfully */ |
376 |
rc=0; |
377 |
printf("LCMAPS succeeded.\n"); |
378 |
|
379 |
/* Print contents of account */ |
380 |
lcmaps_print_account(&account); |
381 |
|
382 |
finalize: |
383 |
/* Close library */ |
384 |
dlclose(lib.handle); |
385 |
return rc; |
386 |
} |
387 |
|
388 |
int lcmaps_nogsi_account(char *my_dn, char *fqan, FILE *logfile) { |
389 |
int rc; |
390 |
lcmaps_library_t lib; |
391 |
lcmaps_account_info_t account; |
392 |
|
393 |
char ** fqans = NULL; |
394 |
|
395 |
fqans = malloc(sizeof(char*) * 2); |
396 |
fqans[0] = fqan; |
397 |
|
398 |
/* Load lcmaps library and symbols */ |
399 |
if (loadlcmaps(&lib, LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI)) |
400 |
return 1; |
401 |
|
402 |
/* Do a run */ |
403 |
if ( (rc=lib.lcmaps_init(logfile)) ) { |
404 |
fprintf(stderr,"lcmaps_init() failed\n"); |
405 |
goto finalize; |
406 |
} |
407 |
if ( (rc=lib.lcmaps_account_info_init(&account)) ) { |
408 |
fprintf(stderr,"lcmaps_account_info_init() failed.\n"); |
409 |
goto finalize; |
410 |
} |
411 |
if ( (rc=lib.lcmaps_return_account_without_gsi(my_dn, fqans, 1, 0, &account)) ) { |
412 |
fprintf(stderr,"lcmaps_return_account_from_pem() failed.\n"); |
413 |
goto finalize; |
414 |
} |
415 |
if ( (rc=lib.lcmaps_term()) ) { |
416 |
fprintf(stderr,"lcmaps_term() failed.\n"); |
417 |
goto finalize; |
418 |
} |
419 |
/* LCMAPS finished succesfully */ |
420 |
rc=0; |
421 |
printf("LCMAPS succeeded.\n"); |
422 |
|
423 |
/* Print contents of account */ |
424 |
lcmaps_print_account(&account); |
425 |
|
426 |
finalize: |
427 |
/* Close library */ |
428 |
dlclose(lib.handle); |
429 |
return rc; |
430 |
} |
431 |
|
432 |
|
433 |
/* Parses the options for LCAS and opens the logfile when needed */ |
434 |
int lcas_set_vars(char *options,char **rsl,FILE **log) { |
435 |
char *var=options,*value,*end,*pos; |
436 |
|
437 |
/* If first char of options is a - it's actually the next main option */ |
438 |
if (options[0]=='-') |
439 |
return 0; |
440 |
|
441 |
do { |
442 |
/* Find end of current var=value pair */ |
443 |
end=strchr(var, ','); |
444 |
if (end!=NULL) end[0]='\0'; |
445 |
/* Find end of variable name */ |
446 |
pos=strchr(var,'='); |
447 |
if (pos==NULL) |
448 |
fprintf(stderr,"Unrecognized element '%s'\n", var); |
449 |
else { |
450 |
pos[0]='\0'; |
451 |
value=pos+1; |
452 |
/* Find the variable */ |
453 |
if (strcmp(var,"debug")==0) |
454 |
setenv("LCAS_DEBUG_LEVEL",value,1); |
455 |
/* else if (strcmp(var,"log")==0) |
456 |
setenv("LCAS_LOG_LEVEL",value,1);*/ |
457 |
else if (strcmp(var,"db")==0) |
458 |
setenv("LCAS_DB_FILE",value,1); |
459 |
else if (strcmp(var,"rsl")==0) |
460 |
*rsl=strdup(value); |
461 |
else if (strcmp(var,"file")==0) { |
462 |
/* Only open when not already linked to stderr */ |
463 |
if (*log==NULL) { |
464 |
if ( (*log=fopen(value,"a"))==NULL) |
465 |
fprintf(stderr,"Cannot open %s: %s\n", |
466 |
value,strerror(errno)); |
467 |
} |
468 |
} |
469 |
else |
470 |
fprintf(stderr,"Unrecognized option '%s'\n",var); |
471 |
/* reset value at pos */ |
472 |
pos[0]='='; |
473 |
} |
474 |
if (end!=NULL) { |
475 |
/* reset value at end */ |
476 |
end[0]=','; |
477 |
/* advance to next option */ |
478 |
var=end+1; |
479 |
} |
480 |
} while (end!=NULL); |
481 |
return 0; |
482 |
} |
483 |
/* Dynamically loads LCAS library and all needed symbols */ |
484 |
int loadlcas(lcas_library_t *lib) { |
485 |
void *handle; |
486 |
|
487 |
/* Load the library */ |
488 |
if ( (lib->handle=handle= |
489 |
dlopen("liblcas.so",RTLD_NOW | RTLD_GLOBAL))==NULL ) { |
490 |
fprintf(stderr,"Error: %s\n",dlerror()); |
491 |
return 1; |
492 |
} |
493 |
|
494 |
/* Load functions */ |
495 |
if ( (lib->lcas_init= |
496 |
(int (*)(FILE*))dlsym(handle,"lcas_init"))==NULL || |
497 |
(lib->lcas_pem= |
498 |
(int (*)(char*,lcas_request_t))dlsym(handle,"lcas_pem"))==NULL || |
499 |
(lib->lcas_term= |
500 |
(int (*)(void))dlsym(handle,"lcas_term"))==NULL ) { |
501 |
fprintf(stderr,"Error: %s\n",dlerror()); |
502 |
dlclose(handle); |
503 |
return 1; |
504 |
} |
505 |
|
506 |
return 0; |
507 |
} |
508 |
|
509 |
/* Loads LCAS library and does a run, for given pemstring and to logfile or |
510 |
* syslog when logfile is NULL and given rsl (=cmd + argus) */ |
511 |
int lcas(char *pemstring,FILE *logfile,char *rsl) { |
512 |
int rc; |
513 |
lcas_library_t lib; |
514 |
lcas_request_t request; |
515 |
|
516 |
request=(lcas_request_t)rsl; |
517 |
|
518 |
/* Load library and symbols */ |
519 |
if (loadlcas(&lib)) |
520 |
return 1; |
521 |
|
522 |
/* Do a run */ |
523 |
if ( (rc=lib.lcas_init(logfile)) ) { |
524 |
fprintf(stderr,"lcas_init() failed\n"); goto finalize; |
525 |
} |
526 |
if ( (rc=lib.lcas_pem(pemstring,request)) ) { |
527 |
fprintf(stderr,"lcas_pem() failed.\n"); goto finalize; |
528 |
} |
529 |
if ( (rc=lib.lcas_term()) ) { |
530 |
fprintf(stderr,"lcas_term() failed.\n"); goto finalize; |
531 |
} |
532 |
printf("LCAS succeeded.\n"); |
533 |
|
534 |
finalize: |
535 |
/* Close library */ |
536 |
dlclose(lib.handle); |
537 |
return rc; |
538 |
} |
539 |
|
540 |
/* Reads in user proxy (on which mapping is based) from filename */ |
541 |
char *readproxy(const char *filename) { |
542 |
int fd,size; |
543 |
char *pemstring; |
544 |
struct stat st; |
545 |
|
546 |
/* Open file and get size */ |
547 |
if ((fd=open(filename,O_RDONLY))==-1 || fstat(fd,&st)==-1) { |
548 |
fprintf(stderr,"Error: Cannot open or stat file %s: %s\n", |
549 |
filename, strerror(errno)); |
550 |
exit(1); |
551 |
} |
552 |
/* Reserve memory */ |
553 |
if ((pemstring=(char *)malloc((size_t)(st.st_size+sizeof(char))))==NULL) { |
554 |
fprintf(stderr,"Error: Cannot malloc %d bytes for pemstring\n", |
555 |
(int)st.st_size); |
556 |
exit(1); |
557 |
} |
558 |
/* Read file */ |
559 |
size=read(fd,pemstring,(size_t)st.st_size); |
560 |
if (size!=st.st_size) { |
561 |
fprintf(stderr,"Error: Number of bytes read %d != size %d\n", |
562 |
size,(int)st.st_size); |
563 |
exit(1); |
564 |
} |
565 |
/* Close file */ |
566 |
close(fd); |
567 |
/* Add '\0' and return */ |
568 |
pemstring[size]='\0'; |
569 |
return pemstring; |
570 |
} |
571 |
|
572 |
/* Prints out usage information */ |
573 |
void usage(char *prog) { |
574 |
int uid=(int)getuid(); |
575 |
|
576 |
printf("Usage: %s [options]\n\n",prog); |
577 |
printf("Valid options are:\n" |
578 |
" -h print this help text.\n\n" |
579 |
" -s send output to stderr instead of syslog or file.\n" |
580 |
" -q quiet output (no warnings).\n" |
581 |
" -p<file> read pemstring from given file.\n" |
582 |
" -x<file> set or override X509_USER_PROXY to given file.\n\n" |
583 |
" -V<dir> set or override X509_VOMS_DIR to given dir.\n" |
584 |
" -C<dir> set or override X509_CERT_DIR to given dir.\n\n" |
585 |
" -L[opts] run LCAS with given options: " |
586 |
"<var>=<value>,<var=value>,...\n" |
587 |
" db=<file> set or override LCAS_DB_FILE.\n" |
588 |
" debug=<level> set or override LCAS_DEBUG_LEVEL.\n" |
589 |
/* " log=<level> set or override LCAS_LOG_LEVEL (which is ignored).\n"*/ |
590 |
" rsl=<string> set rsl string (needs to be quoted).\n" |
591 |
" file=<file> send debug/log output to file instead of " |
592 |
"syslog, ignored\n when -s is specified.\n" |
593 |
"\n -l[opts] run LCMAPS with given options: " |
594 |
"<var>=<value>,<var=value>,...\n" |
595 |
" db=<file> set or override LCMAPS_DB_FILE.\n" |
596 |
" policy=<name> set or override LCMAPS_POLICY_NAME.\n" |
597 |
" debug=<level> set or override LCMAPS_DEBUG_LEVEL.\n" |
598 |
/* " log=<level> set or override LCMAPS_LOG_LEVEL (which is ignored).\n"*/ |
599 |
" file=<file> send debug/log output to file instead of " |
600 |
"syslog, ignored\n when -s is specified.\n\n" |
601 |
" LCMAPS normally extracts all information from a PEM string (i.e. a proxy \n" |
602 |
" certificate), but it can be run in a mode \"without_gsi\" where the data such\n" |
603 |
" as the DN and FQAN are passed as plain strings, as set on the command line.\n" |
604 |
" with -d and -f.\n" |
605 |
" -m pem run LCMAPS get_account with full pem string (default).\n" |
606 |
" -m nogsi_pi run LCMAPS return_poolindex_without_gsi\n" |
607 |
" -m nogsi_ga run LCMAPS return_account_without_gsi\n" |
608 |
" -d<DN> use DN (in without_gsi mode)\n" |
609 |
" -f<FQAN> use FQAN (in without_gsi mode)\n" |
610 |
); |
611 |
printf("\nExample:\n"); |
612 |
printf(" %s -s -p/tmp/x509up_u%d -x/tmp/x509up_u%d \\\n",prog,uid,uid); |
613 |
printf(" -L debug=5,db=/tmp/lcas.db \\\n"); |
614 |
printf(" -l policy=glexec_get_account,debug=5,db=/tmp/lcmaps.db\n"); |
615 |
printf("\nNotes on reproducing gLExec behaviour:\n"); |
616 |
printf("- gLExec uses an LCMAPS policy named 'glexec_get_account'\n"); |
617 |
printf("- the proxy specified with -p is the analog of the GLEXEC_CLIENT_CERT.\n"); |
618 |
|
619 |
exit(0); |
620 |
} |
621 |
|
622 |
int main(int argc, char *argv[]) { |
623 |
extern char *optarg; |
624 |
extern int optind, optopt; |
625 |
int opt,rc=0; |
626 |
|
627 |
/* logfile NULL means logging to syslog */ |
628 |
FILE *lcmaps_logfile=NULL,*lcas_logfile=NULL; |
629 |
int do_lcas=0,do_lcmaps=0,verbose=1; |
630 |
char *pemstring=NULL,*rsl=NULL; |
631 |
lcmaps_mode_t mode = LCMAPS_RETURN_ACCOUNT_FROM_PEM; |
632 |
char *dn = NULL; |
633 |
char *fqan = NULL; |
634 |
|
635 |
/* Parse the commandline options */ |
636 |
while ((opt = getopt(argc, argv, ":hsqp:x:V:C:l:L:m:d:f:")) != -1) { |
637 |
switch (opt) { |
638 |
case 'h': |
639 |
usage(argv[0]); |
640 |
case 's': /* Do not log to file but to stderr */ |
641 |
if (lcmaps_logfile && lcmaps_logfile!=stderr) |
642 |
fclose(lcmaps_logfile); |
643 |
if (lcas_logfile && lcas_logfile!=stderr) |
644 |
fclose(lcas_logfile); |
645 |
lcmaps_logfile=lcas_logfile=stderr; |
646 |
break; |
647 |
case 'q': |
648 |
verbose=0; |
649 |
break; |
650 |
case 'p': |
651 |
pemstring=readproxy(optarg); |
652 |
break; |
653 |
case 'x': |
654 |
setenv("X509_USER_PROXY",optarg,1); |
655 |
break; |
656 |
case 'V': |
657 |
setenv("X509_VOMS_DIR",optarg,1); |
658 |
break; |
659 |
case 'C': |
660 |
setenv("X509_CERT_DIR",optarg,1); |
661 |
break; |
662 |
case 'l': |
663 |
do_lcmaps=1; |
664 |
lcmaps_set_vars(optarg,&lcmaps_logfile); |
665 |
if (optarg[0]=='-') optind--; |
666 |
break; |
667 |
case 'L': |
668 |
do_lcas=1; |
669 |
lcas_set_vars(optarg,&rsl,&lcas_logfile); |
670 |
if (optarg[0]=='-') optind--; |
671 |
break; |
672 |
case 'm': |
673 |
if (strcmp(optarg, "pem") == 0) { |
674 |
mode = LCMAPS_RETURN_ACCOUNT_FROM_PEM; |
675 |
} else if (strcmp(optarg, "nogsi_pi") == 0) { |
676 |
mode = LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI; |
677 |
} else if (strcmp(optarg, "nogsi_ga") == 0) { |
678 |
mode = LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI; |
679 |
} else { |
680 |
fprintf(stderr, "option -m requires one of pem, nogsi_pi, nogsi_ga.\n" |
681 |
"Use -h for help.\n"); |
682 |
exit(EXIT_FAILURE); |
683 |
} |
684 |
break; |
685 |
case 'd': |
686 |
dn = optarg; |
687 |
break; |
688 |
case 'f': |
689 |
fqan = optarg; |
690 |
break; |
691 |
case ':': |
692 |
/* Option did not receive an expected argument (only when last |
693 |
* of line get here, otherwise next option is used as argument), |
694 |
* includes those with optional arguments, i.e. -l and -L */ |
695 |
switch(optopt) { |
696 |
case 'l': |
697 |
do_lcmaps=1; |
698 |
break; |
699 |
case 'L': |
700 |
do_lcas=1; |
701 |
break; |
702 |
default: |
703 |
fprintf(stderr,"%s: option requires an argument -- '%c'\n", |
704 |
argv[0],optopt); |
705 |
fprintf(stderr,"Try `%s -h` for more information.\n",argv[0]); |
706 |
exit(1); |
707 |
} |
708 |
break; |
709 |
case '?': |
710 |
fprintf(stderr,"%s: invalid option -- '%c'\n", argv[0], optopt); |
711 |
fprintf(stderr,"Try `%s -h` for more information.\n",argv[0]); |
712 |
exit(1); |
713 |
} |
714 |
} |
715 |
|
716 |
/* Check if we have something to do... */ |
717 |
if (do_lcas==0 && do_lcmaps==0) { |
718 |
printf("Nothing to do, see %s -h for valid options.\n",argv[0]); |
719 |
return 0; |
720 |
} |
721 |
|
722 |
/* Print warnings when verbose */ |
723 |
if (verbose) { |
724 |
if (pemstring==NULL) |
725 |
fprintf(stderr,"Warning: Empty pemstring for proxy.\n"); |
726 |
if (getenv("X509_USER_PROXY")==NULL) |
727 |
fprintf(stderr,"Warning: X509_USER_PROXY is not set.\n"); |
728 |
if (do_lcas) { |
729 |
if (lcas_logfile==NULL) |
730 |
fprintf(stderr,"Warning: LCAS logging will go to syslog.\n"); |
731 |
if (getenv("LCAS_DB_FILE")==NULL) |
732 |
fprintf(stderr,"Warning: using LCAS default db file.\n"); |
733 |
} |
734 |
if (do_lcmaps) { |
735 |
if (lcmaps_logfile==NULL) |
736 |
fprintf(stderr,"Warning: LCMAPS logging will go to syslog.\n"); |
737 |
if (getenv("LCMAPS_DB_FILE")==NULL) |
738 |
fprintf(stderr,"Warning: using LCMAPS default db file.\n"); |
739 |
if (getenv("LCMAPS_POLICY_NAME")==NULL) |
740 |
fprintf(stderr,"Warning: using LCMAPS default policy name.\n"); |
741 |
if ( (mode == LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI || |
742 |
mode == LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI) && |
743 |
dn == NULL) |
744 |
fprintf(stderr,"Warning: running without GSI with NULL DN string.\n"); |
745 |
} |
746 |
} |
747 |
|
748 |
/* Do LCAS when requested */ |
749 |
if (do_lcas) { |
750 |
rc=lcas(pemstring,lcas_logfile,rsl); |
751 |
if (rc!=0) fprintf(stderr,"LCAS failed.\n"); |
752 |
free(rsl); |
753 |
} |
754 |
|
755 |
/* Do LCMAPS when requested */ |
756 |
if (do_lcmaps) { |
757 |
switch (mode) { |
758 |
case LCMAPS_RETURN_ACCOUNT_FROM_PEM: |
759 |
rc=lcmaps_pem(pemstring,lcmaps_logfile); |
760 |
break; |
761 |
case LCMAPS_RETURN_POOLINDEX_WITHOUT_GSI: |
762 |
rc=lcmaps_nogsi_pool(dn,fqan,lcmaps_logfile); |
763 |
break; |
764 |
case LCMAPS_RETURN_ACCOUNT_WITHOUT_GSI: |
765 |
rc=lcmaps_nogsi_account(dn,fqan,lcmaps_logfile); |
766 |
} |
767 |
if (rc!=0) fprintf(stderr,"LCMAPS failed.\n"); |
768 |
} |
769 |
|
770 |
free(pemstring); |
771 |
|
772 |
return rc; |
773 |
} |