~ubuntu-branches/ubuntu/gutsy/wireshark/gutsy-security

« back to all changes in this revision

Viewing changes to asn1/snmp/packet-snmp-template.c

  • Committer: Bazaar Package Importer
  • Author(s): Frederic Peters
  • Date: 2007-04-01 08:58:40 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070401085840-or3qhrpv8alt1bwg
Tags: 0.99.5-1
* New upstream release.
* debian/patches/09_idl2wrs.dpatch: updated to patch idl2wrs.sh.in.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 * Updated to use the asn2wrs compiler made by Tomas Kukosa
13
13
 * Copyright (C) 2005 - 2006 Anders Broman [AT] ericsson.com
14
14
 *
 
15
 * See RFC 3414 for User-based Security Model for SNMPv3
 
16
 * See RFC 3826 for  (AES) Cipher Algorithm in the SNMP USM
 
17
 * Copyright (C) 2007 Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
15
18
 *
16
 
 * $Id: packet-snmp-template.c 18695 2006-07-10 01:05:24Z gerald $
 
19
 * $Id: packet-snmp-template.c 20399 2007-01-12 00:33:32Z gerald $
17
20
 *
18
21
 * Wireshark - Network traffic analyzer
19
22
 * By Gerald Combs <gerald@wireshark.org>
64
67
 
65
68
#include "packet-ber.h"
66
69
 
67
 
#ifdef HAVE_SOME_SNMP
68
 
 
69
70
#ifdef HAVE_NET_SNMP
70
71
# include <net-snmp/net-snmp-config.h>
71
72
# include <net-snmp/mib_api.h>
72
73
# include <net-snmp/library/default_store.h>
73
74
# include <net-snmp/config_api.h>
74
 
#else /* HAVE_NET_SNMP */
75
 
# include <ucd-snmp/ucd-snmp-config.h>
76
 
# include <ucd-snmp/asn1.h>
77
 
# include <ucd-snmp/snmp_api.h>
78
 
# include <ucd-snmp/snmp_impl.h>
79
 
# include <ucd-snmp/mib.h>
80
 
# include <ucd-snmp/default_store.h>
81
 
# include <ucd-snmp/read_config.h>
82
 
# include <ucd-snmp/tools.h>
83
 
#endif /* HAVE_NET_SNMP */
84
 
 
85
 
#ifndef NETSNMP_DS_LIBRARY_ID
86
 
# define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
87
 
# define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
88
 
# define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
89
 
# define netsnmp_ds_set_boolean ds_set_boolean
90
 
# define netsnmp_ds_set_int ds_set_int
91
 
#endif
92
75
 
93
76
#ifdef _WIN32
94
77
# include <epan/filesystem.h>
109
92
# define VALTYPE_BITSTR         ASN_BIT_STR
110
93
# define VALTYPE_COUNTER64      ASN_COUNTER64
111
94
 
112
 
#endif /* HAVE_SOME_SNMP */
113
 
 
 
95
#endif /* HAVE_NET_SNMP */
114
96
#include "packet-snmp.h"
115
97
#include "format-oid.h"
116
98
 
 
99
#include <epan/crypt/crypt-sha1.h>
 
100
#include <epan/crypt/crypt-md5.h>
 
101
#include <epan/expert.h>
 
102
#include <epan/report_err.h>
 
103
 
 
104
#ifdef _WIN32
 
105
#include <winposixtype.h>
 
106
#endif /* _WIN32 */
 
107
 
 
108
#ifdef HAVE_LIBGCRYPT
 
109
#include <gcrypt.h>
 
110
#endif
 
111
 
 
112
 
117
113
/* Take a pointer that may be null and return a pointer that's not null
118
114
   by turning null pointers into pointers to the above null string,
119
115
   and, if the argument pointer wasn't null, make sure we handle
151
147
static gboolean display_oid = TRUE;
152
148
static gboolean snmp_var_in_tree = TRUE;
153
149
 
 
150
static const gchar* ue_assocs_filename = "";
 
151
static const gchar* ue_assocs_filename_loaded = "";
 
152
static snmp_ue_assoc_t* ue_assocs = NULL;
 
153
static snmp_ue_assoc_t* localized_ues = NULL;
 
154
static snmp_ue_assoc_t* unlocalized_ues = NULL;
 
155
 
 
156
static snmp_usm_params_t usm_p = {FALSE,FALSE,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,FALSE};
 
157
 
154
158
/* Subdissector tables */
155
159
static dissector_table_t variable_oid_dissector_table;
156
160
 
186
190
static int hf_snmp_engineid_time = -1;
187
191
static int hf_snmp_engineid_data = -1;
188
192
static int hf_snmp_counter64 = -1;
 
193
static int hf_snmp_decryptedPDU = -1;
 
194
static int hf_snmp_msgAuthentication = -1;
189
195
 
190
196
#include "packet-snmp-hf.c"
191
197
 
197
203
static gint ett_snmp = -1;
198
204
static gint ett_engineid = -1;
199
205
static gint ett_msgFlags = -1;
 
206
static gint ett_encryptedPDU = -1;
 
207
static gint ett_decrypted = -1;
 
208
static gint ett_authParameters = -1;
200
209
 
201
210
#include "packet-snmp-ett.c"
202
211
 
 
212
 
 
213
static const true_false_string auth_flags = {
 
214
        "OK",
 
215
        "Failed"
 
216
};
 
217
 
203
218
/* defined in net-SNMP; include/net-snmp/library/snmp.h */
204
219
#undef SNMP_MSG_GET
205
220
#undef SNMP_MSG_SET
392
407
        int len;
393
408
        unsigned int i;
394
409
        char *buf;
395
 
#ifdef HAVE_SOME_SNMP
 
410
#ifdef HAVE_NET_SNMP
396
411
        guchar *oid_string;
397
412
        size_t oid_string_len;
398
413
        size_t oid_out_len;
400
415
 
401
416
        result_len = oid_length * 22;
402
417
 
403
 
#ifdef HAVE_SOME_SNMP
 
418
#ifdef HAVE_NET_SNMP
404
419
        /*
405
420
         * Get the decoded form of the OID, and add its length to the
406
421
         * length of the result string.
429
444
                buf += len;
430
445
        }
431
446
 
432
 
#ifdef HAVE_SOME_SNMP
 
447
#ifdef HAVE_NET_SNMP
433
448
        /*
434
449
         * Append the decoded form of the OID.
435
450
         */
448
463
        int len;
449
464
        unsigned int i;
450
465
        char *buf;
451
 
#ifdef HAVE_SOME_SNMP
 
466
#ifdef HAVE_NET_SNMP
452
467
        guchar *oid_string;
453
468
        size_t oid_string_len;
454
469
        size_t oid_out_len;
459
474
                return;
460
475
        }
461
476
 
462
 
#ifdef HAVE_SOME_SNMP
 
477
#ifdef HAVE_NET_SNMP
463
478
        /*
464
479
         * Get the decoded form of the OID, and add its length to the
465
480
         * length of the result string.
498
513
        }
499
514
}
500
515
 
501
 
#ifdef HAVE_SOME_SNMP
 
516
#ifdef HAVE_NET_SNMP
502
517
static gboolean
503
518
check_var_length(guint vb_length, guint required_length, guchar **errmsg)
504
519
{
796
811
        gint oid_len;
797
812
        guint variable_oid_length = 0;
798
813
        const guint8 *var_oid_buf;
799
 
#ifdef HAVE_SOME_SNMP
 
814
#ifdef HAVE_NET_SNMP
800
815
        struct variable_list variable;
801
816
        long value;
802
817
#endif
842
857
        switch (vb_type) {
843
858
 
844
859
        case SNMP_INTEGER:
845
 
                offset = dissect_ber_integer(FALSE, pinfo, NULL, tvb, start, -1, &vb_integer_value);
 
860
                offset = dissect_ber_integer(FALSE, pinfo, NULL, tvb, start, -1, (void*)&(vb_integer_value));
846
861
                length = offset - vb_value_start;
847
862
                if (snmp_tree) {
848
 
#ifdef HAVE_SOME_SNMP
 
863
#ifdef HAVE_NET_SNMP
849
864
                        value = vb_integer_value;
850
865
                        variable.val.integer = &value;
851
866
                        vb_display_string = format_var(&variable,
873
888
                offset = dissect_ber_integer(FALSE, pinfo, NULL, tvb, start, -1, &vb_uinteger_value);
874
889
                length = offset - vb_value_start;
875
890
                if (snmp_tree) {
876
 
#ifdef HAVE_SOME_SNMP
 
891
#ifdef HAVE_NET_SNMP
877
892
                        value = vb_uinteger_value;
878
893
                        variable.val.integer = &value;
879
894
                        vb_display_string = format_var(&variable,
907
922
 
908
923
                length = offset - vb_value_start;
909
924
                if (snmp_tree) {
910
 
#ifdef HAVE_SOME_SNMP
 
925
#ifdef HAVE_NET_SNMP
911
926
                        variable.val.string = vb_octet_string;
912
927
                        vb_display_string = format_var(&variable,
913
928
                            variable_oid, variable_oid_length, vb_type,
977
992
                offset = offset + vb_length;
978
993
                length = offset - vb_value_start;
979
994
                if (snmp_tree) {
980
 
#ifdef HAVE_SOME_SNMP
 
995
#ifdef HAVE_NET_SNMP
981
996
                        variable.val.objid = vb_oid;
982
997
                        vb_display_string = format_var(&variable,
983
998
                            variable_oid, variable_oid_length, vb_type,
991
1006
                                    vb_value_start, length,
992
1007
                                    "Value: %s: [Out of memory]", vb_type_name);
993
1008
                        }
994
 
#else /* HAVE_SOME_SNMP */
 
1009
#else /* HAVE_NET_SNMP */
995
1010
                        vb_display_string = format_oid(vb_oid, vb_oid_length);
996
1011
                        if (vb_display_string != NULL) {
997
1012
                                proto_tree_add_text(snmp_tree, tvb,
1003
1018
                                    vb_value_start, length,
1004
1019
                                    "Value: %s: [Out of memory]", vb_type_name);
1005
1020
                        }
1006
 
#endif /* HAVE_SOME_SNMP */
 
1021
#endif /* HAVE_NET_SNMP */
1007
1022
                }
1008
1023
                break;
1009
1024
 
1040
1055
        return;
1041
1056
}
1042
1057
 
 
1058
 
 
1059
 
 
1060
 
 
1061
 
 
1062
#define CACHE_INSERT(c,a) if (c) { snmp_ue_assoc_t* t = c; c = a; c->next = t; } else { c = a; a->next = NULL; }
 
1063
 
 
1064
static void renew_ue_cache(void) {
 
1065
        if (ue_assocs) {
 
1066
                static snmp_ue_assoc_t* a;
 
1067
 
 
1068
                localized_ues = NULL;
 
1069
                unlocalized_ues = NULL;
 
1070
 
 
1071
                for(a = ue_assocs; a->user.userName.data; a++) {
 
1072
                        if (a->engine.data) {
 
1073
                                CACHE_INSERT(localized_ues,a);
 
1074
                        } else {
 
1075
                                CACHE_INSERT(unlocalized_ues,a);
 
1076
                        }
 
1077
 
 
1078
                }
 
1079
        }
 
1080
}
 
1081
 
 
1082
 
 
1083
static snmp_ue_assoc_t* localize_ue( snmp_ue_assoc_t* o, const guint8* engine, guint engine_len ) {
 
1084
        snmp_ue_assoc_t* n = se_memdup(o,sizeof(snmp_ue_assoc_t));
 
1085
        guint key_size = n->user.authModel->key_size;
 
1086
 
 
1087
        n->engine.data = se_memdup(engine,engine_len);
 
1088
        n->engine.len = engine_len;
 
1089
 
 
1090
        n->user.authKey.data = se_alloc(key_size);
 
1091
        n->user.authKey.len = key_size;
 
1092
        n->user.authModel->pass2key(n->user.authPassword.data,
 
1093
                                                                n->user.authPassword.len,
 
1094
                                                                engine,
 
1095
                                                                engine_len,
 
1096
                                                                n->user.authKey.data);
 
1097
 
 
1098
        n->user.privKey.data = se_alloc(key_size);
 
1099
        n->user.privKey.len = key_size;
 
1100
        n->user.authModel->pass2key(n->user.privPassword.data,
 
1101
                                                                n->user.privPassword.len,
 
1102
                                                                engine,
 
1103
                                                                engine_len,
 
1104
                                                                n->user.privKey.data);
 
1105
 
 
1106
        return n;
 
1107
}
 
1108
 
 
1109
 
 
1110
#define localized_match(a,u,ul,e,el) \
 
1111
        ( a->user.userName.len == ul \
 
1112
        && a->engine.len == el \
 
1113
        && memcmp( a->user.userName.data, u, (a->user.userName.len < ul) ? a->user.userName.len : ul ) == 0 \
 
1114
        && memcmp( a->engine.data,   e, (a->engine.len   < el) ? a->engine.len   : el ) == 0 )
 
1115
 
 
1116
#define unlocalized_match(a,u,l) \
 
1117
        ( a->user.userName.len == l && memcmp( a->user.userName.data, u, a->user.userName.len < l ? a->user.userName.len : l) == 0 )
 
1118
 
 
1119
static snmp_ue_assoc_t* get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb) {
 
1120
        static snmp_ue_assoc_t* a;
 
1121
        guint given_username_len;
 
1122
        guint8* given_username;
 
1123
        guint given_engine_len;
 
1124
        guint8* given_engine;
 
1125
 
 
1126
        if ( ! (localized_ues || unlocalized_ues ) ) return NULL;
 
1127
 
 
1128
        if (! ( user_tvb && engine_tvb ) ) return NULL;
 
1129
 
 
1130
        given_username_len = tvb_length_remaining(user_tvb,0);
 
1131
        given_username = ep_tvb_memdup(user_tvb,0,-1);
 
1132
        given_engine_len = tvb_length_remaining(engine_tvb,0);
 
1133
        given_engine = ep_tvb_memdup(engine_tvb,0,-1);
 
1134
 
 
1135
        for (a = localized_ues; a; a = a->next) {
 
1136
                if ( localized_match(a, given_username, given_username_len, given_engine, given_engine_len) ) {
 
1137
                        return a;
 
1138
                }
 
1139
        }
 
1140
 
 
1141
        for (a = unlocalized_ues; a; a = a->next) {
 
1142
                if ( unlocalized_match(a, given_username, given_username_len) ) {
 
1143
                        snmp_ue_assoc_t* n = localize_ue( a, given_engine, given_engine_len );
 
1144
                        CACHE_INSERT(localized_ues,n);
 
1145
                        return n;
 
1146
                }
 
1147
        }
 
1148
 
 
1149
        return NULL;
 
1150
}
 
1151
 
 
1152
static void destroy_ue_assocs(snmp_ue_assoc_t* assocs) {
 
1153
        if (assocs) {
 
1154
                snmp_ue_assoc_t* a;
 
1155
 
 
1156
                for(a = assocs; a->user.userName.data; a++) {
 
1157
                        g_free(a->user.userName.data);
 
1158
                        if (a->user.authKey.data) g_free(a->user.authKey.data);
 
1159
                        if (a->user.privKey.data) g_free(a->user.privKey.data);
 
1160
                        if (a->engine.data) g_free(a->engine.data);
 
1161
                }
 
1162
 
 
1163
                g_free(ue_assocs);
 
1164
        }
 
1165
}
 
1166
 
 
1167
 
 
1168
gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error) {
 
1169
        guint msg_len;
 
1170
        guint8* msg;
 
1171
        guint auth_len;
 
1172
        guint8* auth;
 
1173
        guint8* key;
 
1174
        guint key_len;
 
1175
        guint8 calc_auth[16];
 
1176
        guint start;
 
1177
        guint end;
 
1178
        guint i;
 
1179
 
 
1180
        if (!p->auth_tvb) {
 
1181
                *error = "No Authenticator";
 
1182
                return FALSE;
 
1183
        }
 
1184
 
 
1185
        key = p->user_assoc->user.authKey.data;
 
1186
        key_len = p->user_assoc->user.authKey.len;
 
1187
 
 
1188
        if (! key ) {
 
1189
                *error = "User has no authKey";
 
1190
                return FALSE;
 
1191
        }
 
1192
 
 
1193
 
 
1194
        auth_len = tvb_length_remaining(p->auth_tvb,0);
 
1195
 
 
1196
        if (auth_len != 12) {
 
1197
                *error = "Authenticator length wrong";
 
1198
                return FALSE;
 
1199
        }
 
1200
 
 
1201
        msg_len = tvb_length_remaining(p->msg_tvb,0);
 
1202
        msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
 
1203
 
 
1204
 
 
1205
        auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
 
1206
 
 
1207
        start = p->auth_offset - p->start_offset;
 
1208
        end =   start + auth_len;
 
1209
 
 
1210
        /* fill the authenticator with zeros */
 
1211
        for ( i = start ; i < end ; i++ ) {
 
1212
                msg[i] = '\0';
 
1213
        }
 
1214
 
 
1215
        md5_hmac(msg, msg_len, key, key_len, calc_auth);
 
1216
 
 
1217
        if (calc_auth_p) *calc_auth_p = calc_auth;
 
1218
        if (calc_auth_len_p) *calc_auth_len_p = 12;
 
1219
 
 
1220
        return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
 
1221
}
 
1222
 
 
1223
 
 
1224
gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_auth_len_p,  gchar const** error _U_) {
 
1225
        guint msg_len;
 
1226
        guint8* msg;
 
1227
        guint auth_len;
 
1228
        guint8* auth;
 
1229
        guint8* key;
 
1230
        guint key_len;
 
1231
        guint8 calc_auth[20];
 
1232
        guint start;
 
1233
        guint end;
 
1234
        guint i;
 
1235
 
 
1236
        if (!p->auth_tvb) {
 
1237
                *error = "No Authenticator";
 
1238
                return FALSE;
 
1239
        }
 
1240
 
 
1241
        key = p->user_assoc->user.authKey.data;
 
1242
        key_len = p->user_assoc->user.authKey.len;
 
1243
 
 
1244
        if (! key ) {
 
1245
                *error = "User has no authKey";
 
1246
                return FALSE;
 
1247
        }
 
1248
 
 
1249
 
 
1250
        auth_len = tvb_length_remaining(p->auth_tvb,0);
 
1251
 
 
1252
 
 
1253
        if (auth_len != 12) {
 
1254
                *error = "Authenticator length wrong";
 
1255
                return FALSE;
 
1256
        }
 
1257
 
 
1258
        msg_len = tvb_length_remaining(p->msg_tvb,0);
 
1259
        msg = ep_tvb_memdup(p->msg_tvb,0,msg_len);
 
1260
 
 
1261
        auth = ep_tvb_memdup(p->auth_tvb,0,auth_len);
 
1262
 
 
1263
        start = p->auth_offset - p->start_offset;
 
1264
        end =   start + auth_len;
 
1265
 
 
1266
        /* fill the authenticator with zeros */
 
1267
        for ( i = start ; i < end ; i++ ) {
 
1268
                msg[i] = '\0';
 
1269
        }
 
1270
 
 
1271
        sha1_hmac(key, key_len, msg, msg_len, calc_auth);
 
1272
 
 
1273
        if (calc_auth_p) *calc_auth_p = calc_auth;
 
1274
        if (calc_auth_len_p) *calc_auth_len_p = 12;
 
1275
 
 
1276
        return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
 
1277
}
 
1278
 
 
1279
tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_) {
 
1280
#ifdef HAVE_LIBGCRYPT
 
1281
    gcry_error_t err;
 
1282
    gcry_cipher_hd_t hd = NULL;
 
1283
 
 
1284
        guint8* cleartext;
 
1285
        guint8* des_key = p->user_assoc->user.privKey.data; /* first 8 bytes */
 
1286
        guint8* pre_iv = &(p->user_assoc->user.privKey.data[8]); /* last 8 bytes */
 
1287
        guint8* salt;
 
1288
        gint salt_len;
 
1289
        gint cryptgrm_len;
 
1290
        guint8* cryptgrm;
 
1291
        tvbuff_t* clear_tvb;
 
1292
        guint8 iv[8];
 
1293
        guint i;
 
1294
 
 
1295
 
 
1296
        salt_len = tvb_length_remaining(p->priv_tvb,0);
 
1297
 
 
1298
        if (salt_len != 8)  {
 
1299
                *error = "decryptionError: msgPrivacyParameters lenght != 8";
 
1300
                return NULL;
 
1301
        }
 
1302
 
 
1303
        salt = ep_tvb_memdup(p->priv_tvb,0,salt_len);
 
1304
 
 
1305
        /*
 
1306
         The resulting "salt" is XOR-ed with the pre-IV to obtain the IV.
 
1307
         */
 
1308
        for (i=0; i<8; i++) {
 
1309
                iv[i] = pre_iv[i] ^ salt[i];
 
1310
        }
 
1311
 
 
1312
        cryptgrm_len = tvb_length_remaining(encryptedData,0);
 
1313
 
 
1314
        if (cryptgrm_len % 8) {
 
1315
                *error = "decryptionError: the length of the encrypted data is not a mutiple of 8 octets";
 
1316
                return NULL;
 
1317
        }
 
1318
 
 
1319
        cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
 
1320
 
 
1321
        cleartext = ep_alloc(cryptgrm_len);
 
1322
 
 
1323
        err = gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0);
 
1324
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1325
 
 
1326
    err = gcry_cipher_setiv(hd, iv, 8);
 
1327
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1328
 
 
1329
        err = gcry_cipher_setkey(hd,des_key,8);
 
1330
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1331
 
 
1332
        err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
 
1333
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1334
 
 
1335
        gcry_cipher_close(hd);
 
1336
 
 
1337
        clear_tvb = tvb_new_real_data(cleartext, cryptgrm_len, cryptgrm_len);
 
1338
 
 
1339
        return clear_tvb;
 
1340
 
 
1341
on_gcry_error:
 
1342
        *error = (void*)gpg_strerror(err);
 
1343
        if (hd) gcry_cipher_close(hd);
 
1344
        return NULL;
 
1345
#else
 
1346
        *error = "libgcrypt not present, cannot decrypt";
 
1347
        return NULL;
 
1348
#endif
 
1349
}
 
1350
 
 
1351
tvbuff_t* snmp_usm_priv_aes(snmp_usm_params_t* p _U_, tvbuff_t* encryptedData _U_, gchar const** error _U_) {
 
1352
#ifdef HAVE_LIBGCRYPT
 
1353
    gcry_error_t err;
 
1354
    gcry_cipher_hd_t hd = NULL;
 
1355
 
 
1356
        guint8* cleartext;
 
1357
        guint8* aes_key = p->user_assoc->user.privKey.data; /* first 16 bytes */
 
1358
        guint8 iv[16];
 
1359
        gint priv_len;
 
1360
        gint cryptgrm_len;
 
1361
        guint8* cryptgrm;
 
1362
        tvbuff_t* clear_tvb;
 
1363
 
 
1364
        priv_len = tvb_length_remaining(p->priv_tvb,0);
 
1365
 
 
1366
        if (priv_len != 8)  {
 
1367
                *error = "decryptionError: msgPrivacyParameters lenght != 8";
 
1368
                return NULL;
 
1369
        }
 
1370
 
 
1371
        iv[0] = (p->boots & 0xff000000) >> 24;
 
1372
        iv[1] = (p->boots & 0x00ff0000) >> 16;
 
1373
        iv[2] = (p->boots & 0x0000ff00) >> 8;
 
1374
        iv[3] = (p->boots & 0x000000ff);
 
1375
        iv[4] = (p->time & 0xff000000) >> 24;
 
1376
        iv[5] = (p->time & 0x00ff0000) >> 16;
 
1377
        iv[6] = (p->time & 0x0000ff00) >> 8;
 
1378
        iv[7] = (p->time & 0x000000ff);
 
1379
        tvb_memcpy(p->priv_tvb,&(iv[8]),0,8);
 
1380
 
 
1381
        cryptgrm_len = tvb_length_remaining(encryptedData,0);
 
1382
        cryptgrm = ep_tvb_memdup(encryptedData,0,-1);
 
1383
 
 
1384
        cleartext = ep_alloc(cryptgrm_len);
 
1385
 
 
1386
        err = gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB, 0);
 
1387
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1388
 
 
1389
    err = gcry_cipher_setiv(hd, iv, 16);
 
1390
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1391
 
 
1392
        err = gcry_cipher_setkey(hd,aes_key,16);
 
1393
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1394
 
 
1395
        err = gcry_cipher_decrypt(hd, cleartext, cryptgrm_len, cryptgrm, cryptgrm_len);
 
1396
        if (err != GPG_ERR_NO_ERROR) goto on_gcry_error;
 
1397
 
 
1398
        gcry_cipher_close(hd);
 
1399
 
 
1400
        clear_tvb = tvb_new_real_data(cleartext, cryptgrm_len, cryptgrm_len);
 
1401
 
 
1402
        return clear_tvb;
 
1403
 
 
1404
on_gcry_error:
 
1405
        *error = (void*)gpg_strerror(err);
 
1406
        if (hd) gcry_cipher_close(hd);
 
1407
        return NULL;
 
1408
#else
 
1409
        *error = "libgcrypt not present, cannot decrypt";
 
1410
        return NULL;
 
1411
#endif
 
1412
}
 
1413
 
 
1414
 
 
1415
gboolean check_ScopedPdu(tvbuff_t* tvb) {
 
1416
        int offset;
 
1417
        gint8 class;
 
1418
        gboolean pc;
 
1419
        gint32 tag;
 
1420
        int hoffset, eoffset;
 
1421
        guint32 len;
 
1422
 
 
1423
        offset = get_ber_identifier(tvb, 0, &class, &pc, &tag);
 
1424
        offset = get_ber_length(NULL, tvb, offset, NULL, NULL);
 
1425
 
 
1426
        if ( ! (((class!=BER_CLASS_APP) && (class!=BER_CLASS_PRI) )
 
1427
                        && ( (!pc) || (class!=BER_CLASS_UNI) || (tag!=BER_UNI_TAG_ENUMERATED) )
 
1428
                        )) return FALSE;
 
1429
 
 
1430
        if((tvb_get_guint8(tvb, offset)==0)&&(tvb_get_guint8(tvb, offset+1)==0))
 
1431
                return TRUE;
 
1432
 
 
1433
        hoffset = offset;
 
1434
 
 
1435
        offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
 
1436
        offset = get_ber_length(NULL, tvb, offset, &len, NULL);
 
1437
        eoffset = offset + len;
 
1438
 
 
1439
        if (eoffset <= hoffset) return FALSE;
 
1440
 
 
1441
        if ((class!=BER_CLASS_APP)&&(class!=BER_CLASS_PRI))
 
1442
                if( (class!=BER_CLASS_UNI)
 
1443
                        ||((tag<BER_UNI_TAG_NumericString)&&(tag!=BER_UNI_TAG_OCTETSTRING)&&(tag!=BER_UNI_TAG_UTF8String)) )
 
1444
                        return FALSE;
 
1445
 
 
1446
        return TRUE;
 
1447
 
 
1448
}
 
1449
 
1043
1450
#include "packet-snmp-fn.c"
1044
1451
 
 
1452
 
1045
1453
guint
1046
1454
dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
1047
1455
    proto_tree *tree, int proto, gint ett, gboolean is_tcp)
1059
1467
        proto_tree *snmp_tree = NULL;
1060
1468
        proto_item *item = NULL;
1061
1469
 
 
1470
        usm_p.msg_tvb = tvb;
 
1471
        usm_p.start_offset = offset_from_real_beginning(tvb,0) ;
 
1472
        usm_p.engine_tvb = NULL;
 
1473
        usm_p.user_tvb = NULL;
 
1474
        usm_p.auth_item = NULL;
 
1475
        usm_p.auth_tvb = NULL;
 
1476
        usm_p.auth_offset = 0;
 
1477
        usm_p.priv_tvb = NULL;
 
1478
        usm_p.user_assoc = NULL;
 
1479
        usm_p.authenticated = FALSE;
 
1480
        usm_p.encrypted = FALSE;
 
1481
        usm_p.boots = 0;
 
1482
        usm_p.time = 0;
 
1483
        usm_p.authOK = FALSE;
 
1484
 
1062
1485
        /*
1063
1486
         * This will throw an exception if we don't have any data left.
1064
1487
         * That's what we want.  (See "tcp_dissect_pdus()", which is
1288
1711
        dissect_SMUX_PDUs_PDU(tvb, pinfo, tree);
1289
1712
}
1290
1713
 
 
1714
 
 
1715
/*
 
1716
  MD5 Password to Key Algorithm
 
1717
  from RFC 3414 A.2.1
 
1718
*/
 
1719
void snmp_usm_password_to_key_md5(const guint8 *password,
 
1720
                                                                  guint   passwordlen,
 
1721
                                                                  const guint8 *engineID,
 
1722
                                                                  guint   engineLength,
 
1723
                                                                  guint8 *key)  {
 
1724
        md5_state_t     MD;
 
1725
        guint8     *cp, password_buf[64];
 
1726
        guint32      password_index = 0;
 
1727
        guint32      count = 0, i;
 
1728
        guint8          key1[16];
 
1729
        md5_init(&MD);   /* initialize MD5 */
 
1730
 
 
1731
        /**********************************************/
 
1732
        /* Use while loop until we've done 1 Megabyte */
 
1733
        /**********************************************/
 
1734
        while (count < 1048576) {
 
1735
                cp = password_buf;
 
1736
                for (i = 0; i < 64; i++) {
 
1737
                        /*************************************************/
 
1738
                        /* Take the next octet of the password, wrapping */
 
1739
                        /* to the beginning of the password as necessary.*/
 
1740
                        /*************************************************/
 
1741
                        *cp++ = password[password_index++ % passwordlen];
 
1742
                }
 
1743
                md5_append(&MD, password_buf, 64);
 
1744
                count += 64;
 
1745
        }
 
1746
        md5_finish(&MD, key1);          /* tell MD5 we're done */
 
1747
 
 
1748
        /*****************************************************/
 
1749
        /* Now localize the key with the engineID and pass   */
 
1750
        /* through MD5 to produce final key                  */
 
1751
        /* May want to ensure that engineLength <= 32,       */
 
1752
        /* otherwise need to use a buffer larger than 64     */
 
1753
        /*****************************************************/
 
1754
 
 
1755
        md5_init(&MD);
 
1756
        md5_append(&MD, key1, 16);
 
1757
        md5_append(&MD, engineID, engineLength);
 
1758
        md5_append(&MD, key1, 16);
 
1759
        md5_finish(&MD, key);
 
1760
 
 
1761
        return;
 
1762
}
 
1763
 
 
1764
 
 
1765
 
 
1766
 
 
1767
/*
 
1768
   SHA1 Password to Key Algorithm COPIED from RFC 3414 A.2.2
 
1769
 */
 
1770
 
 
1771
void snmp_usm_password_to_key_sha1(const guint8 *password,
 
1772
                                                                   guint   passwordlen,
 
1773
                                                                   const guint8 *engineID,
 
1774
                                                                   guint   engineLength,
 
1775
                                                                   guint8 *key ) {
 
1776
        sha1_context     SH;
 
1777
        guint8     *cp, password_buf[72];
 
1778
        guint32      password_index = 0;
 
1779
        guint32      count = 0, i;
 
1780
 
 
1781
        sha1_starts(&SH);   /* initialize SHA */
 
1782
 
 
1783
        /**********************************************/
 
1784
        /* Use while loop until we've done 1 Megabyte */
 
1785
        /**********************************************/
 
1786
        while (count < 1048576) {
 
1787
                cp = password_buf;
 
1788
                for (i = 0; i < 64; i++) {
 
1789
                        /*************************************************/
 
1790
                        /* Take the next octet of the password, wrapping */
 
1791
                        /* to the beginning of the password as necessary.*/
 
1792
                        /*************************************************/
 
1793
                        *cp++ = password[password_index++ % passwordlen];
 
1794
                }
 
1795
                sha1_update (&SH, password_buf, 64);
 
1796
                count += 64;
 
1797
        }
 
1798
        sha1_finish(&SH, key);
 
1799
 
 
1800
        /*****************************************************/
 
1801
        /* Now localize the key with the engineID and pass   */
 
1802
        /* through SHA to produce final key                  */
 
1803
        /* May want to ensure that engineLength <= 32,       */
 
1804
        /* otherwise need to use a buffer larger than 72     */
 
1805
        /*****************************************************/
 
1806
        memcpy(password_buf, key, 20);
 
1807
        memcpy(password_buf+20, engineID, engineLength);
 
1808
        memcpy(password_buf+20+engineLength, key, 20);
 
1809
 
 
1810
        sha1_starts(&SH);
 
1811
        sha1_update(&SH, password_buf, 40+engineLength);
 
1812
        sha1_finish(&SH, key);
 
1813
        return;
 
1814
 }
 
1815
 
 
1816
 
1291
1817
static void
1292
1818
process_prefs(void)
1293
1819
{
1294
 
#ifdef HAVE_SOME_SNMP
 
1820
#ifdef HAVE_NET_SNMP
1295
1821
        gchar *tmp_mib_modules;
1296
1822
        static gboolean mibs_loaded = FALSE;
1297
1823
 
1341
1867
        init_mib();
1342
1868
        read_configs();
1343
1869
        mibs_loaded = TRUE;
1344
 
#endif /* HAVE_SOME_SNMP */
 
1870
#endif /* HAVE_NET_SNMP */
 
1871
 
 
1872
        if ( g_str_equal(ue_assocs_filename_loaded,ue_assocs_filename) ) return;
 
1873
        ue_assocs_filename_loaded = ue_assocs_filename;
 
1874
 
 
1875
        if (ue_assocs) destroy_ue_assocs(ue_assocs);
 
1876
 
 
1877
        if ( *ue_assocs_filename ) {
 
1878
                gchar* err = load_snmp_users_file(ue_assocs_filename,&ue_assocs);
 
1879
                if (err) report_failure("Error while loading SNMP's users file:\n%s",err);
 
1880
        } else {
 
1881
                ue_assocs = NULL;
 
1882
        }
1345
1883
}
1346
 
/*--- proto_register_snmp -------------------------------------------*/
 
1884
 
 
1885
 
 
1886
 
 
1887
        /*--- proto_register_snmp -------------------------------------------*/
1347
1888
void proto_register_snmp(void) {
1348
 
 
1349
 
#if defined(_WIN32) && defined(HAVE_SOME_SNMP)
 
1889
#if defined(_WIN32) && defined(HAVE_NET_SNMP)
1350
1890
        char *mib_path;
1351
1891
        int mib_path_len;
1352
1892
#define MIB_PATH_APPEND "snmp\\mibs"
1394
1934
                { &hf_snmp_counter64, {
1395
1935
                    "Value", "snmp.counter64", FT_INT64, BASE_DEC,
1396
1936
                    NULL, 0, "A counter64 value", HFILL }},
 
1937
                  { &hf_snmp_msgAuthentication,
 
1938
                                { "Authentication", "snmp.v3.auth", FT_BOOLEAN, 8,
 
1939
                                        TFS(&auth_flags), 0, "", HFILL }},
 
1940
                  { &hf_snmp_decryptedPDU, {
 
1941
                                        "Decrypted ScopedPDU", "snmp.decrypted_pdu", FT_BYTES, BASE_HEX,
 
1942
                                        NULL, 0, "Decrypted PDU", HFILL }},
1397
1943
 
1398
1944
#include "packet-snmp-hfarr.c"
1399
1945
  };
1403
1949
          &ett_snmp,
1404
1950
          &ett_engineid,
1405
1951
          &ett_msgFlags,
 
1952
          &ett_encryptedPDU,
 
1953
          &ett_decrypted,
 
1954
          &ett_authParameters,
1406
1955
 
1407
1956
#include "packet-snmp-ettarr.c"
1408
1957
  };
1409
1958
        module_t *snmp_module;
1410
1959
 
1411
 
  #ifdef HAVE_SOME_SNMP
 
1960
#ifdef HAVE_NET_SNMP
1412
1961
 
1413
1962
#ifdef _WIN32
1414
1963
        /* Set MIBDIRS so that the SNMP library can find its mibs. */
1424
1973
 
1425
1974
        /*
1426
1975
         * Suppress warnings about unknown tokens - we aren't initializing
1427
 
         * UCD SNMP in its entirety, we're just initializing the
 
1976
         * Net-SNMP in its entirety, we're just initializing the
1428
1977
         * MIB-handling part because that's all we're using, which
1429
1978
         * means that entries in the configuration file for other
1430
1979
         * pars of the library will not be handled, and we don't want
1434
1983
                               NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
1435
1984
        netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
1436
1985
                           NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
1437
 
#endif /* HAVE_SOME_SNMP */
 
1986
#endif /* HAVE_NET_SNMP */
1438
1987
 
1439
1988
 
1440
1989
  /* Register protocol */
1479
2028
                "ON - display dissected variables inside SNMP tree, OFF - display dissected variables in root tree after SNMP",
1480
2029
                &snmp_var_in_tree);
1481
2030
 
 
2031
  prefs_register_string_preference(snmp_module, "users_file",
 
2032
                                                                   "USMuserTable file",
 
2033
                                                                   "The filename of the user table used for authentication and decryption",
 
2034
                                                                   &ue_assocs_filename);
 
2035
 
1482
2036
        variable_oid_dissector_table =
1483
2037
            register_dissector_table("snmp.variable_oid",
1484
2038
              "SNMP Variable OID", FT_STRING, BASE_NONE);
 
2039
 
 
2040
        register_init_routine(renew_ue_cache);
1485
2041
}
1486
2042
 
1487
2043