source: libabac/abac_util.c @ e97d2e2

mei_rt2_fix_1
Last change on this file since e97d2e2 was 4f40c3e, checked in by Mei <mei@…>, 11 years ago

1) add a yap patch file for 6.2.2 for FreeBSD platform
2) update documentaions

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