1 %{ 2 /* 3 * Parser for verified exec fingerprint file. 4 * 5 * $NetBSD: veriexecctl_parse.y,v 1.3 2004/03/06 11:59:30 blymn Exp $ 6 * 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <errno.h> 12 #include <sys/ioctl.h> 13 #include <sys/verified_exec.h> 14 15 /* yacc internal function */ 16 static int yygrowstack __P((void)); 17 int yylex __P((void)); 18 void yyerror __P((const char *)); 19 20 /* function prototypes */ 21 static int 22 convert(char *fp, unsigned int count, unsigned char *out); 23 24 /* ioctl parameter struct */ 25 static struct verified_exec_params params; 26 extern int fd; 27 extern int lineno; 28 29 %} 30 31 %union { 32 char *string; 33 int intval; 34 } 35 36 %token EOL 37 %token <string> PATH 38 %token <string> STRING 39 40 %% 41 42 statement: /* empty */ 43 | statement path type fingerprint flags eol 44 | statement error eol { 45 yyclearin; /* discard lookahead */ 46 yyerrok; /* no more error */ 47 fprintf(stderr, 48 "skipping to next fingerprint\n"); 49 } 50 ; 51 52 path: PATH 53 { 54 if (strlen($1) >= MAXPATHLEN) { 55 yyerror("Path >= MAXPATHLEN"); 56 YYERROR; 57 } 58 strncpy(params.file, $1, MAXPATHLEN); 59 params.type = VERIEXEC_DIRECT; 60 }; 61 62 type: STRING 63 { 64 if (strcasecmp($1, "md5") == 0) { 65 params.fp_type = FINGERPRINT_TYPE_MD5; 66 } else if (strcasecmp($1, "sha1") == 0) { 67 params.fp_type = FINGERPRINT_TYPE_SHA1; 68 } else { 69 fprintf(stderr, "%s %s at %d, %s\n", 70 "veriexecctl: bad fingerprint type", $1, lineno, 71 "assuming MD5"); 72 params.fp_type = FINGERPRINT_TYPE_MD5; 73 } 74 }; 75 76 77 fingerprint: STRING 78 { 79 unsigned int count; 80 81 if (params.fp_type == FINGERPRINT_TYPE_SHA1) 82 count = SHA1_FINGERPRINTLEN; 83 else 84 count = MD5_FINGERPRINTLEN; 85 86 if (convert($1, count, params.fingerprint) < 0) { 87 fprintf(stderr, 88 "veriexecctl: bad fingerprint at line %d\n", 89 lineno); 90 } 91 }; 92 93 flags: /* empty */ 94 | flag_spec flags; 95 96 flag_spec: STRING 97 { 98 params.type = VERIEXEC_DIRECT; 99 if (strcasecmp($1, "indirect") == 0) { 100 params.type = VERIEXEC_INDIRECT; 101 } else if (strcasecmp($1, "file") == 0) { 102 params.type = VERIEXEC_FILE; 103 } 104 }; 105 106 eol: EOL 107 { 108 if (!YYRECOVERING) /* Don't do the ioctl if we saw an error */ 109 do_ioctl(); 110 }; 111 112 %% 113 114 /* 115 * Convert: takes the hexadecimal string pointed to by fp and converts 116 * it to a "count" byte binary number which is stored in the array pointed to 117 * by out. Returns -1 if the conversion fails. 118 */ 119 static int 120 convert(char *fp, unsigned int count, unsigned char *out) 121 { 122 int i, value, error = 0; 123 124 for (i = 0; i < count; i++) { 125 if ((fp[2*i] >= '0') && (fp[2*i] <= '9')) { 126 value = 16 * (fp[2*i] - '0'); 127 } else if ((fp[2*i] >= 'a') && (fp[2*i] <= 'f')) { 128 value = 16 * (10 + fp[2*i] - 'a'); 129 } else { 130 error = -1; 131 break; 132 } 133 134 if ((fp[2*i + 1] >= '0') && (fp[2*i + 1] <= '9')) { 135 value += fp[2*i + 1] - '0'; 136 } else if ((fp[2*i + 1] >= 'a') && (fp[2*i + 1] <= 'f')) { 137 value += fp[2*i + 1] - 'a' + 10; 138 } else { 139 error = -1; 140 break; 141 } 142 143 out[i] = value; 144 } 145 146 return error; 147 } 148 149 /* 150 * Perform the load of the fingerprint. Assumes that the fingerprint 151 * pseudo-device is opened and the file handle is in fd. 152 */ 153 static void 154 do_ioctl(void) 155 { 156 if (ioctl(fd, VERIEXECLOAD, ¶ms) < 0) 157 fprintf(stderr, "Ioctl failed with error `%s' on file %s\n", 158 strerror(errno), params.file); 159 } 160