/** ** abac_util.c **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "abac_util.h" static int debug=0; /* Callback configuration */ struct cb_opts { int use_prompt; /* Print a prompt to stderr */ int use_echo; /* If true, turn off input echo on stdin */ unsigned int tries; /* Number of attempts allowed */ char prompt[20]; /* The prompt to display if use_echo is true */ }; /** potato pw length */ #define PWLEN 128 /** SHA string length */ #define SHA1_LENGTH 40 /****************************************************************/ char *abac_version() { DEBUG_PRINTF("abac_version is %s\n", ABAC_VERSION); return ABAC_VERSION; } char *prologIt(char *str) { char *tmp=NULL; asprintf(&tmp,"p%s",str); return tmp; } void abac_clean_string(char *string) { int len=strlen(string); int i; for(i=0;icrypto->create_rng(lib->crypto, RNG_WEAK); if (!rng) errx(1, "no random number generator"); rng->allocate_bytes(rng, 8, &serial); while (serial.ptr[0] == 0) { // don't get leading 0's rng->get_bytes(rng, 1, serial.ptr); } rng->destroy(rng); DEBUG_PRINTF("abac_generate_serial, serial generated is %#B\n", &serial); return serial; } // validate a princpal's name // makes sure it's a valid SHA1 identifier // return values: // success: malloc'd copy with all hex digits lowercase // fail: NULL char *abac_validate_principal(char *keyid) { int i; char *copy = NULL; if (strlen(keyid) != SHA1_LENGTH) return NULL; int len = strlen(keyid) + 1; copy = abac_xmalloc(len); sprintf(copy, "%s", keyid); i=0; for (; i < SHA1_LENGTH; ++i) { copy[i] = tolower(copy[i]); if (!isxdigit(copy[i])) goto error; } return copy; error: free(copy); return NULL; } // parse&validate the validity int abac_validate_validity_string(char *validity_str) { int validity=0; if (validity_str != NULL) { char suffix = 'd'; // default suffix is days int multiplier; int len = strlen(validity_str); assert(len > 0); // get the suffix char if it's alphabetical if (isalpha(validity_str[len - 1])) { suffix = validity_str[len - 1]; // truncate validity_str[len - 1] = '\0'; --len; // make sure it's not only a suffix if (len == 0) { errx(1,"Invalid validity\n"); } } // convert the suffix to a multiplier switch(suffix) { case 's': multiplier = 1; break; case 'm': multiplier = 60; break; case 'h': multiplier = 3600; break; case 'd': multiplier = 86400; break; case 'y': multiplier = 31536000; break; default: errx(1,"Invalid suffix, must be s m h d y\n"); } // ascii to int char *end; validity = strtol(validity_str, &end, 10); if (end - validity_str < len) { errx(1,"Invalid validity\n"); } if (validity <= 0) { errx(1,"Invalid validity: must be > 0\n"); } // multiply! validity *= multiplier; } return validity; } int file_exist(char *filename) { struct stat stbuf; if(stat(filename,&stbuf) == -1) return 0; return 1; } chunk_t abac_get_potato_file(char *filename) { chunk_t pp=chunk_empty; if(file_exist(filename)) { DEBUG_PRINTF("trying to open %s\n", filename); FILE *fp=fopen(filename,"r"); char str[PWLEN]; int rc=fscanf(fp,"%s",str); if(rc) { pp.ptr=abac_xstrdup(str); pp.len=strlen(pp.ptr); if(str[pp.len-1]=='\n') pp.len--; } abac_clean_string(str); fclose(fp); } return pp; } /*** ***/ chunk_t abac_get_potato_cb(int try, char *name) { /* Get a password from stdin and return it as a chunk_t. If too many tries * have occurred or there is any other problem, return an empty chunk_t, * which libstrongswan takes as giving up. The chunk is alloated here * (inside getline), and presumably freed by libstrongswan. User points to * a cb_opts struct, which affects this routine in the obvious ways. */ /* Configuration options */ if(name!=NULL) { char *n=(char *)memrchr(name,'/',strlen(name)); if(n==NULL) printf("[%s] ", name); else printf("[%s] ",n); } struct cb_opts c_opts = { 1, 0, 3, "Key passphrase:" }; struct cb_opts *opts = &c_opts; chunk_t rv = chunk_empty; /* Return value, starts empty */ if (try -1 < opts->tries ) { struct termios t; /* Terminal settings */ size_t len = 0; /* Length of string from getline */ tcflag_t orig = 0; /* Holds the original local flags (echo in here) */ if (!opts->use_echo) { /* Use tc{get,set}attr to turn echo off and restore the intial * echo settings */ if (!tcgetattr(0, &t)) { orig = t.c_lflag; t.c_lflag &= ~ECHO; if ( tcsetattr(0, TCSANOW, &t) ) { perror("Cannot turn off echo"); return rv; } } else { perror("Cannot turn get attributes to off echo"); return rv; } } if (opts->use_prompt) printf("%s", opts->prompt); /* Because rv.ptr starts as NULL, getline allocates memory. The size * of the allocation returns in rv.len and the size of the string * (including newline and NUL) is in len. */ if ((rv.ptr = (u_char *) malloc(rv.len = PWLEN))) { if ( fgets(rv.ptr, rv.len, stdin) ) { /* Readjust the chunk_t's len field to the size of the string * w/o the newline or NUL */ /* would prefer strnlen, but no such luck in FBSD7 or earlier*/ size_t len = strlen(rv.ptr); /* \n\0, \n or \0 */ if (rv.ptr[len-2] == '\n') rv.len = len-2; else if (rv.ptr[len-1] == '\n') rv.len = len-1; else rv.len = len -1; } else { /* Read failed. Deallocate and clear rv */ free(rv.ptr); rv = chunk_empty; } } else { /* Failed malloc. Restore rv to empty and return it */ perror("malloc"); rv = chunk_empty; return rv; } if (!opts->use_echo ) { /* Pop echo beck to its original setting. */ t.c_lflag = orig; if ( tcsetattr(0, TCSANOW, &t) ) perror("Cannot restore echo setting?"); if (opts->use_prompt) printf("\n"); } } else fprintf(stderr, "Too many tries (%d)", try-1); return rv; } chunk_t extract_potato(char *filename, char *pfile) { chunk_t pp; if(pfile==NULL || strlen(pfile)==0 ) { pp=abac_get_potato_cb(2,filename); } else { pp=abac_get_potato_file(pfile); } return pp; }