3 %option prefix="Snmp_UE_file_"
4 %option never-interactive
9 * load_snmp_users_file.l
11 * User-based Security Model for SNMPv3
12 * SNMP user-engine association file parser
14 * Copyright 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
18 * Wireshark - Network traffic analyzer
19 * By Gerald Combs <gerald@wireshark.org>
20 * Copyright 1998 Gerald Combs
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #include <epan/tvbuff.h>
48 #include <epan/proto.h>
49 #include <epan/packet_info.h>
50 #include <epan/emem.h>
52 #include <epan/dissectors/packet-snmp.h>
59 static GString* error;
60 static GArray* assoc_arr = NULL;
62 static guint8* engine = NULL;
63 static guint engine_len = 0;
64 static guint8* user = NULL;
65 static guint user_len = 0;
66 static guint8* auth_password = NULL;
67 static guint auth_password_len = 0;
68 static guint8* priv_password = NULL;
69 static guint priv_password_len = 0;
70 static int auth = AUTH_MD5;
71 static int enc = PRIV_DES;
72 static guint linenum = 0;
73 static const gchar* filename = "";
74 static guint loaded = 0;
76 static void add_engine(void);
77 static guint8* unhexbytes(const char* s, guint len, guint* len_p);
78 static guint8* undquote(const char* s, guint in_len, guint* len_p);
80 static snmp_usm_auth_model_t model_md5 = {snmp_usm_password_to_key_md5, snmp_usm_auth_md5, 16};
81 static snmp_usm_auth_model_t model_sha1 = {snmp_usm_password_to_key_sha1, snmp_usm_auth_sha1, 20};
84 #define START_LINE() { \
90 auth_password = NULL;\
91 auth_password_len = 0;\
92 priv_password = NULL;\
93 priv_password_len = 0;\
101 hex_bytes [0-9A-Fa-f]+
102 quoted_string \042([^\042]|\134\042)*\042
111 comment [ \t]*\043[^\n]*\n
113 %START START_ENGINE STOP_ENGINE
114 %START START_USER STOP_USER
115 %START START_AUTHPASSWORD STOP_AUTHPASSWORD
116 %START START_PRIVPASSWORD STOP_PRIVPASSWORD
122 <ERRORED>{newline} { START_LINE(); }
124 <START_ENGINE>{newline} { START_LINE(); }
125 <START_ENGINE>{comment} { START_LINE(); }
127 <START_ENGINE>{quoted_string} { engine = undquote(yytext, yyleng, &engine_len); BEGIN STOP_ENGINE; }
128 <START_ENGINE>{hex_bytes} { engine = unhexbytes(yytext, yyleng, &engine_len); BEGIN STOP_ENGINE; }
129 <START_ENGINE>{any_engine} { engine = NULL; engine_len = 0; BEGIN STOP_ENGINE; }
130 <START_ENGINE>. { ERR("Invalid engineId"); }
132 <STOP_ENGINE>{whitespace} { BEGIN START_USER; }
134 <START_USER>{quoted_string} { user = undquote(yytext, yyleng,&user_len); BEGIN STOP_USER; }
135 <START_USER>{hex_bytes} { user = unhexbytes(yytext, yyleng, &user_len); BEGIN STOP_USER; }
136 <START_USER>. { ERR("Invalid userName"); }
138 <STOP_USER>{whitespace} { BEGIN START_AUTHPASSWORD; }
140 <START_AUTHPASSWORD>{quoted_string} { auth_password = undquote(yytext, yyleng, &auth_password_len); BEGIN STOP_AUTHPASSWORD; }
141 <START_AUTHPASSWORD>{hex_bytes} { auth_password = unhexbytes(yytext, yyleng, &auth_password_len); BEGIN STOP_AUTHPASSWORD; }
142 <START_AUTHPASSWORD>. { ERR("Invalid authPassword"); }
144 <STOP_AUTHPASSWORD>{whitespace} { BEGIN START_PRIVPASSWORD; }
146 <START_PRIVPASSWORD>{quoted_string} { priv_password = undquote(yytext, yyleng, &priv_password_len); BEGIN STOP_PRIVPASSWORD; }
147 <START_PRIVPASSWORD>{hex_bytes} { priv_password = unhexbytes(yytext, yyleng, &priv_password_len); BEGIN STOP_PRIVPASSWORD; }
148 <START_PRIVPASSWORD>. { ERR("Invalid privPassword"); }
150 <STOP_PRIVPASSWORD>{whitespace} { BEGIN ATTRIBUTES; }
151 <STOP_PRIVPASSWORD>{newline} { add_engine(); START_LINE(); }
153 <ATTRIBUTES>{whitespace} ;
154 <ATTRIBUTES>{md5} { auth = AUTH_MD5; }
155 <ATTRIBUTES>{sha} { auth = AUTH_SHA; }
156 <ATTRIBUTES>{des} { enc = PRIV_DES; }
157 <ATTRIBUTES>{aes} { enc = PRIV_AES; }
158 <ATTRIBUTES>{newline} { add_engine(); START_LINE(); }
159 <ATTRIBUTES>. { ERR("Invalid char in attributes"); }
163 static guint8* unhexbytes(const char* si, guint len, guint* len_p) {
166 const guint8* s = (void*)si;
170 ERR("Uneven number of chars hex string");
177 for (i = 0; i<len ; i += 2) {
181 if (hi >= '0' && hi <= '9') {
183 } else if (hi >= 'a' && hi <= 'f') {
186 } else if (hi >= 'A' && hi <= 'F') {
193 if (lo >= '0' && lo <= '9') {
195 } else if (lo >= 'a' && lo <= 'f') {
198 } else if (lo >= 'A' && lo <= 'F') {
205 *(p++) = (hi*0x10) + lo;
210 if (len_p) *len_p = len;
215 ERR("Error parsing hex string");
220 static guint8* undquote(const char* si, guint in_len, guint* len_p) {
221 guint8* buf = g_malloc(in_len); /* wastes one byte for every '\\' in text */
224 guint8* end = buf+in_len;
225 const guint8* s = (void*)si;
227 for (s++; p < end; s++) {
234 case 'a': *(p++) = '\a'; len++; break;
235 case 'b': *(p++) = '\b'; len++; break;
236 case 'e': *(p++) = '\e'; len++; break;
237 case 'f': *(p++) = '\f'; len++; break;
238 case 'n': *(p++) = '\n'; len++; break;
239 case 'r': *(p++) = '\r'; len++; break;
240 case 't': *(p++) = '\t'; len++; break;
241 case 'v': *(p++) = '\v'; len++; break;
258 if ( s[1] >= '0' && s[1] <= '7' ) {
262 if ( s[1] >= '0' && s[1] <= '7' ) {
268 c = (64 * c2) + (8 * c1) + c0;
269 *(p++) = (char) (c > 255 ? 255 : c);
288 while ( p < end ) *(p++) = '\0';
291 if (len_p) *len_p = len;
297 static void add_engine(void) {
302 a.user.userName.data = user;
303 a.user.userName.len = user_len;
305 a.user.authPassword.data = auth_password;
306 a.user.authPassword.len = auth_password_len;
308 a.user.privPassword.data = priv_password;
309 a.user.privPassword.len = priv_password_len;
313 a.user.authModel = &model_md5;
316 a.user.authModel = &model_sha1;
319 g_assert_not_reached();
325 a.user.privProtocol = snmp_usm_priv_des;
328 a.user.privProtocol = snmp_usm_priv_aes;
331 g_assert_not_reached();
336 a.engine.data = engine;
337 a.engine.len = engine_len;
339 if (a.user.authModel) {
340 a.user.authKey.data = g_malloc(a.user.authModel->key_size);
341 a.user.authKey.len = a.user.authModel->key_size;
342 a.user.privKey.data = g_malloc(a.user.authModel->key_size);
343 a.user.privKey.len = a.user.authModel->key_size;
344 a.user.authModel->pass2key( auth_password, auth_password_len, engine, engine_len, a.user.authKey.data);
345 a.user.authModel->pass2key( priv_password, priv_password_len, engine, engine_len, a.user.privKey.data);
347 a.user.authKey.data = NULL;
348 a.user.authKey.len = 0;
349 a.user.privKey.data = NULL;
350 a.user.privKey.len = 0;
354 a.engine.data = NULL;
356 a.user.authKey.data = NULL;
357 a.user.authKey.len = 0;
358 a.user.privKey.data = NULL;
359 a.user.privKey.len = 0;
364 g_array_append_val(assoc_arr,a);
370 gchar* load_snmp_users_file(const char* fname, snmp_ue_assoc_t** assocs) {
371 gchar* err_str = NULL;
375 assoc_arr = g_array_new(TRUE,FALSE,sizeof(snmp_ue_assoc_t));
378 yyin = fopen(filename,"r");
381 return ep_strdup_printf("Could not open file: '%s', error: %s",filename,strerror(errno));
384 error = g_string_new("");
396 *assocs = (snmp_ue_assoc_t*)assoc_arr->data;
397 g_array_free(assoc_arr,FALSE);
400 g_array_free(assoc_arr,TRUE);
405 err_str = error->str;