source: libabac/abac_util.c @ f89b991

mei_rt2
Last change on this file since f89b991 was 2e9455f, checked in by Mei <mei@…>, 11 years ago

1) added namespace
2) tweak ?This,
3) allowing linking role/oset as constraining conditions
4) adding access_tests regression testing that uses GENI's access policy
5) added couple multi contexts regression tests
6) add compression/uncompression calls to abac_encode_string/abac_decode_string
(libstrongwan only allows 512 char for attribute rule storage)
7) add attribute_now option to creddy that takes a whole char string for attribute
rule

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/**
2** abac_util.c
3**/
4#include <err.h>
5#include <stdlib.h>
6#include <string.h>
7#include <stdio.h>
8#include <assert.h>
9#include <stdarg.h>
10#include <sys/stat.h>
11#include <termios.h>
12#include <unistd.h>
13#include <sys/types.h>
14
15#include <credentials/certificates/certificate.h>
16#include <credentials/certificates/x509.h>
17#include <credentials/keys/private_key.h>
18
19#include "abac_util.h"
20
21static int debug=0;
22
23/* Callback configuration */
24struct cb_opts {
25    int use_prompt;                   /* Print a prompt to stderr */
26    int use_echo;        /* If true, turn off input echo on stdin */
27    unsigned int tries;             /* Number of attempts allowed */
28    char prompt[20]; /* The prompt to display if use_echo is true */
29};
30
31/**  potato pw length */
32#define PWLEN 128
33
34/** SHA string length */
35#define SHA1_LENGTH 40
36
37/****************************************************************/
38char *abac_version()
39{
40   DEBUG_PRINTF("abac_version is %s\n", ABAC_VERSION);
41   return ABAC_VERSION;
42}
43
44char *prologIt(char *str)
45{
46    char *tmp=NULL;
47    asprintf(&tmp,"p%s",str);
48    return tmp;
49}
50
51void abac_clean_string(char *string)
52{
53   int len=strlen(string);
54   int i;
55   for(i=0;i<len;i++)
56       string[i]=0;
57}
58
59void abac_errx(int eval, const char *msg)
60{
61   errx(eval,"%s",msg);
62}
63
64/**
65 * Malloc, fatal on error.
66 */
67void *abac_xmalloc(size_t size) {
68    void *ret;
69   
70    ret = malloc(size);
71    if (ret == NULL)
72        err(1, "malloc");
73
74    return ret;
75}
76
77void *abac_xrealloc(void *ptr, size_t size) {
78    void *ret = realloc(ptr, size);
79    if (ret == NULL)
80        err(1, "couldn't realloc %d bytes\n", size);
81    return ret;
82}
83
84
85/**
86 * strdup fatal on error
87 */
88char *abac_xstrdup(char *source) {
89    char *ret;
90
91    if (source == NULL) {
92        return NULL;
93    }
94
95    ret = strdup(source);
96    if (ret == NULL)
97        err(1, "strdup");
98
99    return ret;
100}
101
102/* make a brand new string with or without being trimmed */
103char *abac_trim_quotes(char *string) {
104    char *tmp=abac_xstrdup(string);
105    int len=strlen(tmp);
106    if( (tmp[len-1] == '\'' || tmp[len-1] == '"') &&
107                       (tmp[0] == '\'' || tmp[0] == '"')) {
108       tmp[len-1]='\0';
109       char *ntmp=abac_xstrdup(&tmp[1]);
110       free(tmp);
111       return ntmp;
112    }
113    return tmp;
114}
115
116/**
117 * Split a string based on the given delimiter.
118 */
119void abac_split(char *string, char *delim, char **ret, int *num) {
120    int len = strlen(delim);
121    char *start = string;
122    int count = 0;
123
124    // split the string by the delim
125    while ((start = strstr(string, delim)) != NULL) {
126        *start = 0;
127        ret[count++] = string;
128        string = start + len;
129    }
130    ret[count++] = string;
131
132    *num = count;
133}
134
135int abac_validate_clean_name(char *string) {
136    int i;
137
138    assert(string != NULL);
139
140    // must start with a letter/number
141    if (!isalnum(string[0])) return 0;
142
143    // Name must be alphanumeric or -
144    for (i = 1; string[i] != '\0'; ++i)
145        if (!isalnum(string[i]) && string[i] != '-')
146            return 0;
147
148    return 1;
149}
150
151/* check up to first ( if its there..
152   a.role(this)
153   a.role(?,?Year:[100..200],?Value:[one,two,three])
154   a.role(isi)
155*/
156int abac_validate_clean_aspect_name(char *string) {
157    int i;
158
159    assert(string != NULL);
160
161    // must start with a letter/number
162    if (!isalnum(string[0])) return 0;
163
164    // Name must be alphanumeric or - or _ up to the ( if there is one
165    for (i = 1; string[i] != '\0' && string[i] != '(' ; ++i)
166        if (!isalnum(string[i]) && string[i] != '-' && 
167                    string[i] != '_' )
168            return 0;
169    return 1;
170}
171
172chunk_t abac_generate_serial() {
173    chunk_t serial = chunk_empty;
174
175    // create a serial (stolen from strongswan pki)
176    rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
177    if (!rng)
178        errx(1, "no random number generator");
179
180    rng->allocate_bytes(rng, 8, &serial);
181    while (serial.ptr[0] == 0) {
182        // don't get leading 0's
183        rng->get_bytes(rng, 1, serial.ptr);
184    }
185    rng->destroy(rng);
186
187    DEBUG_PRINTF("abac_generate_serial, serial generated is %#B\n", &serial);
188    return serial;
189}
190
191// validate a princpal's name
192// makes sure it's a valid SHA1 identifier
193// return values:
194//  success: malloc'd copy with all hex digits lowercase
195//  fail: NULL
196char *abac_validate_principal(char *keyid) {
197    int i;
198    char *copy = NULL;
199
200    if (strlen(keyid) != SHA1_LENGTH)
201        return NULL;
202
203    int len = strlen(keyid) + 1;
204    copy = abac_xmalloc(len);
205    sprintf(copy, "%s", keyid);
206
207    i=0;
208    for (; i < SHA1_LENGTH; ++i) {
209        copy[i] = tolower(copy[i]);
210        if (!isxdigit(copy[i]))
211            goto error;
212    }
213    return copy;
214error:
215    free(copy);
216    return NULL;
217}
218
219// parse&validate the validity
220int abac_validate_validity_string(char *validity_str)
221{
222    int validity=0;
223    if (validity_str != NULL) {
224        char suffix = 'd'; // default suffix is days
225        int multiplier;
226
227        int len = strlen(validity_str);
228        assert(len > 0);
229
230        // get the suffix char if it's alphabetical
231        if (isalpha(validity_str[len - 1])) {
232            suffix = validity_str[len - 1];
233
234           // truncate
235            validity_str[len - 1] = '\0';
236            --len;
237
238            // make sure it's not only a suffix
239            if (len == 0) {
240                errx(1,"Invalid validity\n");
241            }
242        }
243
244        // convert the suffix to a multiplier
245        switch(suffix) {
246            case 's': multiplier =        1; break;
247            case 'm': multiplier =       60; break;
248            case 'h': multiplier =     3600; break;
249            case 'd': multiplier =    86400; break;
250            case 'y': multiplier = 31536000; break;
251            default:
252                errx(1,"Invalid suffix, must be s m h d y\n");
253        }
254
255        // ascii to int
256        char *end;
257        validity = strtol(validity_str, &end, 10);
258        if (end - validity_str < len) {
259            errx(1,"Invalid validity\n");
260        }
261
262        if (validity <= 0) {
263            errx(1,"Invalid validity: must be > 0\n");
264        }
265
266        // multiply!
267        validity *= multiplier;
268    }
269    return validity;
270}
271
272
273int file_exist(char *filename)
274{
275   struct stat stbuf;
276   if(stat(filename,&stbuf) == -1)
277       return 0;
278   return 1;
279}
280
281
282chunk_t abac_get_potato_file(char *filename)
283{
284   chunk_t pp=chunk_empty;
285   if(file_exist(filename)) {
286       DEBUG_PRINTF("trying to open %s\n", filename);
287       FILE *fp=fopen(filename,"r");
288       char str[PWLEN]; 
289       int rc=fscanf(fp,"%s",str);
290       if(rc) {
291           pp.ptr=abac_xstrdup(str); 
292           pp.len=strlen(pp.ptr);
293           if(str[pp.len-1]=='\n')
294               pp.len--;
295       }
296       abac_clean_string(str);
297       fclose(fp);
298   }
299   return pp;
300}
301
302/***
303***/
304chunk_t abac_get_potato_cb(int try, char *name) {
305    /* Get a password from stdin and return it as a chunk_t.  If too many tries
306     * have occurred or there is any other problem, return an empty chunk_t,
307     * which libstrongswan takes as giving up.  The chunk is alloated here
308     * (inside getline), and presumably freed by libstrongswan. User points to
309     * a cb_opts struct, which affects this routine in the obvious ways.
310     */
311    /* Configuration options */
312 
313    if(name!=NULL) {
314        char *n=(char *)memrchr(name,'/',strlen(name));
315        if(n==NULL)
316            printf("[%s] ", name);
317            else printf("[%s] ",n);
318    }
319    struct cb_opts c_opts = { 1, 0, 3, "Key passphrase:" };
320    struct cb_opts *opts = &c_opts;
321    chunk_t rv = chunk_empty;   /* Return value, starts empty */
322
323    if (try -1 < opts->tries ) {
324        struct termios t;   /* Terminal settings */
325        size_t len = 0;     /* Length of string from getline */
326        tcflag_t orig = 0;  /* Holds the original local flags (echo in here) */
327
328        if (!opts->use_echo) {
329            /* Use tc{get,set}attr to turn echo off and restore the intial
330             * echo settings */
331            if (!tcgetattr(0, &t)) {
332                orig = t.c_lflag;
333
334                t.c_lflag &= ~ECHO;
335                if ( tcsetattr(0, TCSANOW, &t) ) {
336                    perror("Cannot turn off echo");
337                    return rv;
338                }
339            }
340            else {
341                perror("Cannot turn get attributes to off echo");
342                return rv;
343            }
344        }
345        if (opts->use_prompt) printf("%s", opts->prompt);
346
347        /* Because rv.ptr starts as NULL, getline allocates memory.  The size
348         * of the allocation returns in rv.len and the size of the string
349         * (including newline and NUL) is in len.  */
350        if ((rv.ptr = (u_char *) malloc(rv.len = PWLEN))) {
351            if ( fgets(rv.ptr, rv.len, stdin) ) {
352                /* Readjust the chunk_t's len field to the size of the string
353                 * w/o the newline or NUL */
354                /* would prefer strnlen, but no such luck in FBSD7 or earlier*/
355                size_t len = strlen(rv.ptr);
356
357                /* \n\0, \n or \0 */
358                if (rv.ptr[len-2] == '\n') rv.len = len-2;
359                   else if (rv.ptr[len-1] == '\n') rv.len = len-1;
360                     else rv.len = len -1;
361            } else {
362                /* Read failed.  Deallocate and clear rv */
363                free(rv.ptr);
364                rv = chunk_empty;
365            }
366        }
367        else {
368            /* Failed malloc.  Restore rv to empty and return it */
369            perror("malloc");
370            rv = chunk_empty;
371            return rv;
372        }
373
374        if (!opts->use_echo ) {
375            /* Pop echo beck to its original setting. */
376            t.c_lflag = orig;
377
378            if ( tcsetattr(0, TCSANOW, &t) )
379                perror("Cannot restore echo setting?");
380
381            if (opts->use_prompt) printf("\n");
382        }
383    }
384    else fprintf(stderr, "Too many tries (%d)", try-1);
385    return rv;
386}
387
388chunk_t extract_potato(char *filename, char *pfile)
389{
390    chunk_t pp;
391    if(pfile==NULL || strlen(pfile)==0 ) {
392      pp=abac_get_potato_cb(2,filename);
393      } else {
394        pp=abac_get_potato_file(pfile);
395    }
396    return pp;
397}
Note: See TracBrowser for help on using the repository browser.