source: libabac/abac_util.c @ 5d1b6dc

mei_rt2mei_rt2_fix_1
Last change on this file since 5d1b6dc was 2a73357, checked in by Mei <mei@…>, 12 years ago

1) replace bool return type to int return type. seems to be causing
some unexpected behaviour from gcc compiler

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