Hello all.
I just started working with libfprint.
The first thing I wanted to do was giving better security w/ my reader
(uru4000b), since it keeps the image of the last acquired finger on its
window (someone could easily "steal" it).
The trivial workaround is require more than one finger to login. And
since I was there, I added some options for pam_fprint:
- finger=[-1-9] : force the module to ask for the given finger (-1=auto)
- nfingers=[1-10] : require the use of N different fingers
- randomize=[1|0|true|false...]: randomize the required finger
nfingers implies randomize=true and finger=-1; randomize=true implies
finger=-1;
If no parameter is specified, the usual behaviour is used.
Hope it's interesting for someone else, too.
All comments welcome! :-)
BYtE,
Diego.
21a22
> #include <stdlib.h>
24a26
> #include <time.h>
159c161,225
< static int do_auth(pam_handle_t *pamh)
---
> /* "options" container.
> - Must be terminated by {0, NULL, 0, NULL}
> - if an option in the starting part of another, the longer one must come
> first
> (so if XX and XXY are valid options, XXY must be before XX in the array)
> */
> struct cmdline_options {
> char shortopt; /* short version for the option: f=X */
> char *longopt; /* long version for the option: foo=X */
> int type; /* type of var: 0=int, 1=string, 2=boolean */
> void *var; /* ptr to the target var */
> };
>
> /* Very basic commandline options parser, to avoid other dependencies on
> external libraries */
> static void cmdline_parse(int argc, const char **argv, const struct
> cmdline_options *opts) {
> int c;
> for(c=0; c<argc; ++c) {
> const struct cmdline_options *o=opts; /* struct is const,
> pointer is not! */
> while (o->shortopt || o->longopt) {
> int ol=strlen(o->longopt);
> int found=0;
> if (argv[c][0] == o->shortopt && argv[c][1]=='=') {
> /* is a short opt */
> found=1;
> ol=1;
> } else {
> if ((argv[c][ol] == '=') && /* is a long
> opt */
> (0 == strncmp(argv[c], o->longopt, ol))) {
> found=1;
> }
> }
> if (found) {
> const char *arg=argv[c]+ol+1; /* argument to
> the option */
> switch (o->type) {
> case 0: { /* Integer */
> int *iv=o->var;
> *iv=atoi(arg);
> }
> break;
> case 1: { /* String */
> const char **sv=o->var;
> *sv=arg; /* REFERENCES the
> (constant) argument */
> }
> break;
> case 2: { /* Boolean */
> int *bv=o->var;
> if (tolower(arg[0]) == 'y' ||
> tolower(arg[0]) == 't') {
> *bv=!0;
> } else {
> *bv=0;
> }
> }
> break;
> default:
> /* TODO: Should log "parser error:
> undefined type" */
> break;
> }
> break; /* Jump out of while() */
> }
> ++o; /* Go to next option descriptio */
> }
> /* TODO: here we could check !(o->shortopt || o->longopt) to
> warn about unrecognized options in config file */
> }
> }
>
> static int do_auth(pam_handle_t *pamh, int argc, const char **argv)
168a235,271
> int reqfinger=-1; /* [0-9]; default: autodetect requred finger */
> int reqnfingers=1; /* [1-10]; default: 1 (single finger auth) */
> int randomfingers=0; /* bool, default: false (fixed finger) */
>
>
> const struct cmdline_options opts[]={
> {'f', "finger", 0, &reqfinger},
> {'n', "nfingers", 0, &reqnfingers},
> {'r', "randomize", 2, &randomfingers},
> {0, NULL, 0, NULL} /* terminate array */
> };
> cmdline_parse(argc, argv, opts);
>
> /* "Sanitize" cmdline options */
> if (reqnfingers < 1 || reqnfingers > 10) { /* out of range */
> reqnfingers=1;
> }
> if (reqnfingers > 1) { /* more than one finger implies random fingers
> (no way to supply a list, atm) */
> randomfingers=1;
> }
> if (randomfingers) { /* random implies no fixed finger */
> reqfinger=-1;
> }
>
> #if DEBUG
> {
> char buff[4096];
> char *b=buff;
> for(r=0; r<argc; ++r) {
> b+=sprintf(b, "pam_fprint option: '%s'\n", argv[r]);
> }
> b+=sprintf(b, "reqfinger = %d (%s)\n", reqfinger, fingerstr(reqfinger));
> b+=sprintf(b, "reqnfingers = %d\n", reqnfingers);
> b+=sprintf(b, "randomfingers = %d\n", randomfingers);
> send_info_msg(pamh, buff);
> }
> #endif
184,186c287,298
< r = find_dev_and_print(ddevs, prints, &ddev, &print);
< if (r) {
< fp_dscv_prints_free(prints);
---
> if (reqfinger == -1 && reqnfingers == 1 && randomfingers == 0) {
> /* old behaviour: one, system-chosen, fixed fingerprint */
> r = find_dev_and_print(ddevs, prints, &ddev, &print);
> if (r) {
> fp_dscv_prints_free(prints);
> fp_dscv_devs_free(ddevs);
> send_info_msg(pamh, "Could not locate any suitable
> fingerprints "
> "matched with available hardware.");
> return PAM_AUTHINFO_UNAVAIL;
> }
>
> dev = fp_dev_open(ddev);
188,191c300,303
< send_info_msg(pamh, "Could not locate any suitable fingerprints
"
< "matched with available hardware.");
< return PAM_AUTHINFO_UNAVAIL;
< }
---
> if (!dev) {
> fp_dscv_prints_free(prints);
> return PAM_AUTHINFO_UNAVAIL;
> }
193,198c305
< dev = fp_dev_open(ddev);
< fp_dscv_devs_free(ddevs);
< if (!dev) {
< fp_dscv_prints_free(prints);
< return PAM_AUTHINFO_UNAVAIL;
< }
---
> finger = fp_dscv_print_get_finger(print);
200c307,312
< finger = fp_dscv_print_get_finger(print);
---
> r = fp_print_data_from_dscv_print(print, &data);
> fp_dscv_prints_free(prints);
> if (r) {
> fp_dev_close(dev);
> return PAM_AUTHINFO_UNAVAIL;
> }
202,204c314,315
< r = fp_print_data_from_dscv_print(print, &data);
< fp_dscv_prints_free(prints);
< if (r) {
---
> r = do_verify(pamh, dev, data, finger);
> fp_print_data_free(data);
206,207c317,334
< return PAM_AUTHINFO_UNAVAIL;
< }
---
> } else {
> /* new behaviour */
> int cnt;
> int matched=0; /* num of successfully matched unique
> fingerprints */
>
> struct fingersmap {
> struct fp_dscv_print *fp;
> enum fp_finger fn;
> } fingers[10];/* Shuffle for DIFFERENT random prints */
>
> /* Fill the fingers array */
> for (cnt=0; cnt<10; ++cnt) {
> fingers[cnt].fn=LEFT_THUMB+cnt;
> }
> /* Map discovered fingerprints into the array */
> for (cnt=0; NULL!=(print=prints[cnt]); ++cnt) {
>
> fingers[fp_dscv_print_get_finger(print)-LEFT_THUMB].fp=print;
> }
209,211c336,389
< r = do_verify(pamh, dev, data, finger);
< fp_print_data_free(data);
< fp_dev_close(dev);
---
> if (reqfinger != -1) {
> /* Set the only required finger */
> fingers[0].fp=fingers[reqfinger].fp;
> fingers[0].fn=LEFT_THUMB+reqfinger;
> } else {
> unsigned long ltime=(unsigned long)time(NULL);
> srandom((ltime&0x0000FFFFL)^(ltime>>16));
>
> if (randomfingers) {
> int f1, f2;
> /* Shuffle the fingers array */
> for (cnt=0; cnt<15; ++cnt) {
> enum fp_finger tfn;
> struct fp_dscv_print *tfp;
> f1=random()%10;
> f2=random()%10;
>
> /* swap fingers[f1] and fingers[f2] */
> tfn=fingers[f1].fn;
> fingers[f1].fn=fingers[f2].fn;
> fingers[f2].fn=tfn;
> tfp=fingers[f1].fp;
> fingers[f1].fp=fingers[f2].fp;
> fingers[f2].fp=tfp;
> }
> }
> }
> /* Now try to acquire and verify reqnfingers fingerprints */
> for (cnt=0; cnt<reqnfingers; ++cnt) {
> print=fingers[cnt].fp;
> /* Note that different fingerprints could be on
> different readers! */
> ddev = fp_dscv_dev_for_dscv_print(ddevs, print);
> dev = fp_dev_open(ddev);
> if (!dev) {
> break; //return PAM_AUTHINFO_UNAVAIL;
> }
>
> r = fp_print_data_from_dscv_print(print, &data);
> if (r) {
> fp_dev_close(dev);
> break; //return ;
> }
>
> if(PAM_SUCCESS==do_verify(pamh, dev, data,
> fingers[cnt].fn)) {
> ++matched;
> }
> fp_print_data_free(data);
> fp_dev_close(dev);
> }
> r=(matched==reqnfingers)?PAM_SUCCESS:PAM_AUTH_ERR;
>
> fp_dscv_prints_free(prints);
> fp_dscv_devs_free(ddevs);
> }
249c427
< r = do_auth(pamh);
---
> r = do_auth(pamh, argc, argv);
_______________________________________________
fprint mailing list
[email protected]
http://lists.reactivated.net/mailman/listinfo/fprint