Coverage Report

Created: 2023-06-07 06:42

/src/net-snmp/snmplib/snmptsm.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * snmptsmsm.c -- Implements RFC #5591
3
 *
4
 * This code implements a security model that assumes the local user
5
 * that executed the agent is the user who's attributes are passed up
6
 * by the transport underneath.  The RFC describing this security
7
 * model is RFC5591.
8
 */
9
10
#include <net-snmp/net-snmp-config.h>
11
12
#include <net-snmp/net-snmp-features.h>
13
#include <net-snmp/net-snmp-includes.h>
14
15
#include <net-snmp/library/snmptsm.h>
16
17
#ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
18
#include <net-snmp/library/snmpSSHDomain.h>
19
#endif
20
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
21
#include <net-snmp/library/snmpDTLSUDPDomain.h>
22
#endif
23
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
24
#include <net-snmp/library/snmpTLSTCPDomain.h>
25
#endif
26
#ifdef NETSNMP_TRANSPORT_DTLSSCTP_DOMAIN
27
#include <net-snmp/library/snmpDTLSSCTPDomain.h>
28
#endif
29
30
netsnmp_feature_require(snmpv3_probe_contextEngineID_rfc5343);
31
netsnmp_feature_require(row_create);
32
33
static int      tsm_session_init(netsnmp_session *);
34
static void     tsm_free_state_ref(void *);
35
static int      tsm_clone_pdu(netsnmp_pdu *, netsnmp_pdu *);
36
static int      tsm_free_pdu(netsnmp_pdu *pdu);
37
38
u_int next_sess_id = 1;
39
40
/** Initialize the TSM security module */
41
void
42
init_tsm(void)
43
2.98k
{
44
2.98k
    struct snmp_secmod_def *def;
45
2.98k
    int ret;
46
47
2.98k
    def = SNMP_MALLOC_STRUCT(snmp_secmod_def);
48
49
2.98k
    if (!def) {
50
0
        snmp_log(LOG_ERR,
51
0
                 "Unable to malloc snmp_secmod struct, not registering TSM\n");
52
0
        return;
53
0
    }
54
55
2.98k
    def->encode_reverse = tsm_rgenerate_out_msg;
56
2.98k
    def->decode = tsm_process_in_msg;
57
2.98k
    def->session_open = tsm_session_init;
58
2.98k
    def->pdu_free_state_ref = tsm_free_state_ref;
59
2.98k
    def->pdu_clone = tsm_clone_pdu;
60
2.98k
    def->pdu_free = tsm_free_pdu;
61
2.98k
    def->probe_engineid = snmpv3_probe_contextEngineID_rfc5343;
62
63
2.98k
    DEBUGMSGTL(("tsm","registering ourselves\n"));
64
2.98k
    ret = register_sec_mod(SNMP_SEC_MODEL_TSM, "tsm", def);
65
2.98k
    DEBUGMSGTL(("tsm"," returned %d\n", ret));
66
67
2.98k
    netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "tsmUseTransportPrefix",
68
2.98k
             NETSNMP_DS_LIBRARY_ID,
69
2.98k
                               NETSNMP_DS_LIB_TSM_USE_PREFIX);
70
2.98k
}
71
72
/** shutdown the TSM security module */
73
void
74
shutdown_tsm(void)
75
5.97k
{
76
5.97k
}
77
78
/*
79
 * Initialize specific session information (right now, just set up things to
80
 * not do an engineID probe)
81
 */
82
83
static int
84
tsm_session_init(netsnmp_session * sess)
85
0
{
86
0
    DEBUGMSGTL(("tsm",
87
0
                "TSM: Reached our session initialization callback\n"));
88
89
0
    sess->flags |= SNMP_FLAGS_DONT_PROBE;
90
91
    /* XXX: likely needed for something: */
92
    /*
93
    tsmsession = sess->securityInfo =
94
    if (!tsmsession)
95
        return SNMPERR_GENERR;
96
    */
97
98
0
    return SNMPERR_SUCCESS;
99
0
}
100
101
/** Free our state information (this is only done on the agent side) */
102
static void
103
tsm_free_state_ref(void *ptr)
104
0
{
105
0
    netsnmp_tsmSecurityReference *tsmRef = ptr;
106
107
0
    if (!tsmRef)
108
0
        return;
109
110
    /* the tmStateRef is always taken care of by the normal PDU, since this
111
       is just a reference to that one */
112
    /* DON'T DO: SNMP_FREE(tsmRef->tmStateRef); */
113
    /* SNMP_FREE(tsmRef);  ? */
114
0
}
115
116
static int
117
tsm_free_pdu(netsnmp_pdu *pdu)
118
0
{
119
    /* free the security reference */
120
0
    if (pdu->securityStateRef) {
121
0
        tsm_free_state_ref(pdu->securityStateRef);
122
0
        pdu->securityStateRef = NULL;
123
0
    }
124
0
    return 0;
125
0
}
126
127
/** This is called when a PDU is cloned (to increase reference counts) */
128
static int
129
tsm_clone_pdu(netsnmp_pdu *pdu, netsnmp_pdu *pdu2)
130
0
{
131
0
    netsnmp_tsmSecurityReference *oldref, *newref;
132
133
0
    oldref = pdu->securityStateRef;
134
0
    if (!oldref)
135
0
        return SNMPERR_SUCCESS;
136
137
0
    newref = SNMP_MALLOC_TYPEDEF(netsnmp_tsmSecurityReference);
138
0
    netsnmp_assert_or_return(NULL != newref, SNMPERR_GENERR);
139
0
    DEBUGMSGTL(("tsm", "cloned as pdu=%p, ref=%p (oldref=%p)\n",
140
0
                pdu2, newref, pdu2->securityStateRef));
141
    
142
0
    memcpy(newref, oldref, sizeof(*oldref));
143
144
    /* the tm state reference is just a link to the one in the pdu,
145
       which was already copied by snmp_clone_pdu before handing it to
146
       us. */
147
148
0
    newref->tmStateRef = netsnmp_memdup(oldref->tmStateRef,
149
0
                                        sizeof(*oldref->tmStateRef));
150
0
    if (!newref->tmStateRef) {
151
0
        snmp_log(LOG_ERR, "tsm: malloc failure\n");
152
0
        free(newref);
153
0
        return SNMPERR_GENERR;
154
0
    }
155
156
0
    pdu2->securityStateRef = newref;
157
158
0
    return SNMPERR_SUCCESS;
159
0
}
160
161
/* asn.1 easing definitions */
162
#define TSMBUILD_OR_ERR(fun, args, msg, desc)       \
163
    DEBUGDUMPHEADER("send", desc); \
164
    rc = fun args;            \
165
    DEBUGINDENTLESS();        \
166
    if (rc == 0) { \
167
        DEBUGMSGTL(("tsm",msg)); \
168
        retval = SNMPERR_TOO_LONG; \
169
        goto outerr; \
170
    }
171
172
/****************************************************************************
173
 *
174
 * tsm_generate_out_msg
175
 *
176
 * Parameters:
177
 *  (See list below...)
178
 *
179
 * Returns:
180
 *  SNMPERR_SUCCESS                        On success.
181
 *  ... and others
182
 *
183
 *
184
 * Generate an outgoing message.
185
 *
186
 ****************************************************************************/
187
188
int
189
tsm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
190
0
{
191
0
    u_char         **wholeMsg = parms->wholeMsg;
192
0
    size_t     *offset = parms->wholeMsgOffset;
193
0
    int rc;
194
    
195
0
    size_t         *wholeMsgLen = parms->wholeMsgLen;
196
0
    netsnmp_tsmSecurityReference *tsmSecRef;
197
0
    netsnmp_tmStateReference *tmStateRef;
198
0
    int             tmStateRefLocal = 0;
199
    
200
0
    DEBUGMSGTL(("tsm", "Starting TSM processing\n"));
201
202
    /* if we have this, then this message to be sent is in response to
203
       something that came in earlier and the tsmSecRef was created by
204
       the tsm_process_in_msg. */
205
0
    tsmSecRef = parms->secStateRef;
206
    
207
0
    if (tsmSecRef) {
208
        /* 4.2, step 1: If there is a securityStateReference (Response
209
           or Report message), then this Security Model uses the
210
           cached information rather than the information provided by
211
           the ASI. */
212
213
        /* 4.2, step 1: Extract the tmStateReference from the
214
           securityStateReference cache. */
215
0
        netsnmp_assert_or_return(NULL != tsmSecRef->tmStateRef, SNMPERR_GENERR);
216
0
        tmStateRef = tsmSecRef->tmStateRef;
217
218
        /* 4.2 step 1: Set the tmRequestedSecurityLevel to the value
219
           of the extracted tmTransportSecurityLevel. */
220
0
        tmStateRef->requestedSecurityLevel = tmStateRef->transportSecurityLevel;
221
222
        /* 4.2 step 1: Set the tmSameSecurity parameter in the
223
           tmStateReference cache to true. */
224
0
        tmStateRef->sameSecurity = NETSNMP_TM_USE_SAME_SECURITY;
225
226
        /* 4.2 step 1: The cachedSecurityData for this message can
227
           now be discarded. */
228
0
        SNMP_FREE(parms->secStateRef);
229
0
    } else {
230
        /* 4.2, step 2: If there is no securityStateReference (e.g., a
231
           Request-type or Notification message), then create a
232
           tmStateReference cache. */
233
0
        tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference);
234
0
        netsnmp_assert_or_return(NULL != tmStateRef, SNMPERR_GENERR);
235
0
        tmStateRefLocal = 1;
236
237
        /* XXX: we don't actually use this really in our implementation */
238
        /* 4.2, step 2: Set tmTransportDomain to the value of
239
           transportDomain, tmTransportAddress to the value of
240
           transportAddress */
241
242
        /* 4.2, step 2: and tmRequestedSecurityLevel to the value of
243
           securityLevel. */
244
0
        tmStateRef->requestedSecurityLevel = parms->secLevel;
245
246
        /* 4.2, step 2: Set the transaction-specific tmSameSecurity
247
           parameter to false. */
248
0
        tmStateRef->sameSecurity = NETSNMP_TM_SAME_SECURITY_NOT_REQUIRED;
249
250
0
        if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
251
0
                                   NETSNMP_DS_LIB_TSM_USE_PREFIX)) {
252
            /* XXX: probably shouldn't be a hard-coded list of
253
               supported transports */
254
            /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix
255
               object is set to true, then use the transportDomain to
256
               look up the corresponding prefix. */
257
0
            const char *prefix;
258
0
            if (strncmp("ssh:",parms->session->peername,4) == 0)
259
0
                prefix = "ssh:";
260
0
            else if (strncmp("dtls:",parms->session->peername,5) == 0)
261
0
                prefix = "dtls:";
262
0
            else if (strncmp("tls:",parms->session->peername,4) == 0)
263
0
                prefix = "tls:";
264
0
            else {
265
                /* 4.2, step 2: If the prefix lookup fails for any
266
                   reason, then the snmpTsmUnknownPrefixes counter is
267
                   incremented, an error indication is returned to the
268
                   calling module, and message processing stops. */
269
0
                snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES);
270
0
                SNMP_FREE(tmStateRef);
271
0
                return SNMPERR_GENERR;
272
0
            }
273
274
            /* 4.2, step 2: If the lookup succeeds, but there is no
275
               prefix in the securityName, or the prefix returned does
276
               not match the prefix in the securityName, or the length
277
               of the prefix is less than 1 or greater than 4 US-ASCII
278
               alpha-numeric characters, then the
279
               snmpTsmInvalidPrefixes counter is incremented, an error
280
               indication is returned to the calling module, and
281
               message processing stops. */
282
0
            if (strchr(parms->secName, ':') == 0 ||
283
0
                strlen(prefix)+1 >= parms->secNameLen ||
284
0
                strncmp(parms->secName, prefix, strlen(prefix)) != 0 ||
285
0
                parms->secName[strlen(prefix)] != ':') {
286
                /* Note: since we're assiging the prefixes above the
287
                   prefix lengths always meet the 1-4 criteria */
288
0
                snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDPREFIXES);
289
0
                SNMP_FREE(tmStateRef);
290
0
                return SNMPERR_GENERR;
291
0
            }
292
293
            /* 4.2, step 2: Strip the transport-specific prefix and
294
               trailing ':' character (US-ASCII 0x3a) from the
295
               securityName.  Set tmSecurityName to the value of
296
               securityName. */
297
0
            memcpy(tmStateRef->securityName,
298
0
                   parms->secName + strlen(prefix) + 1,
299
0
                   parms->secNameLen - strlen(prefix) - 1);
300
0
            tmStateRef->securityNameLen = parms->secNameLen - strlen(prefix) -1;
301
0
        } else {
302
            /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix object is
303
               set to false, then set tmSecurityName to the value
304
               of securityName. */
305
0
            memcpy(tmStateRef->securityName, parms->secName,
306
0
                   parms->secNameLen);
307
0
            tmStateRef->securityNameLen = parms->secNameLen;
308
0
        }
309
0
    }
310
311
    /* truncate the security name with a '\0' for safety */
312
0
    tmStateRef->securityName[tmStateRef->securityNameLen] = '\0';
313
314
    /* 4.2, step 3: Set securityParameters to a zero-length OCTET
315
     *  STRING ('0400').
316
     */
317
0
    DEBUGDUMPHEADER("send", "tsm security parameters");
318
0
    rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1,
319
0
                                     (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
320
0
                                             | ASN_OCTET_STR), 0);
321
0
    DEBUGINDENTLESS();
322
0
    if (rc == 0) {
323
0
        DEBUGMSGTL(("tsm", "building msgSecurityParameters failed.\n"));
324
0
        if (tmStateRefLocal)
325
0
            SNMP_FREE(tmStateRef);
326
0
        return SNMPERR_TOO_LONG;
327
0
    }
328
    
329
    /* 4.2, step 4: Combine the message parts into a wholeMsg and
330
       calculate wholeMsgLength.
331
     */
332
0
    while ((*wholeMsgLen - *offset) < parms->globalDataLen) {
333
0
        if (!asn_realloc(wholeMsg, wholeMsgLen)) {
334
0
            DEBUGMSGTL(("tsm", "building global data failed.\n"));
335
0
            if (tmStateRefLocal)
336
0
                SNMP_FREE(tmStateRef);
337
0
            return SNMPERR_TOO_LONG;
338
0
        }
339
0
    }
340
341
0
    *offset += parms->globalDataLen;
342
0
    memcpy(*wholeMsg + *wholeMsgLen - *offset,
343
0
           parms->globalData, parms->globalDataLen);
344
345
    /* 4.2, step 5: The wholeMsg, wholeMsgLength, securityParameters,
346
       and tmStateReference are returned to the calling Message
347
       Processing Model with the statusInformation set to success. */
348
349
    /* For the Net-SNMP implementation that actually means we start
350
       encoding the full packet sequence from here before returning it */
351
352
    /*
353
     * Total packet sequence.  
354
     */
355
0
    rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
356
0
                                     (u_char) (ASN_SEQUENCE |
357
0
                                               ASN_CONSTRUCTOR), *offset);
358
0
    if (rc == 0) {
359
0
        DEBUGMSGTL(("tsm", "building master packet sequence failed.\n"));
360
0
        if (tmStateRefLocal)
361
0
            SNMP_FREE(tmStateRef);
362
0
        return SNMPERR_TOO_LONG;
363
0
    }
364
365
0
    if (parms->pdu->transport_data &&
366
0
        parms->pdu->transport_data != tmStateRef) {
367
0
        snmp_log(LOG_ERR, "tsm: needed to free transport data\n");
368
0
        SNMP_FREE(parms->pdu->transport_data);
369
0
    }
370
371
    /* put the transport state reference into the PDU for the transport */
372
0
    parms->pdu->transport_data = netsnmp_memdup(tmStateRef, sizeof(*tmStateRef));
373
0
    if (tmStateRefLocal)
374
0
        SNMP_FREE(tmStateRef);
375
376
0
    if (!parms->pdu->transport_data) {
377
0
        snmp_log(LOG_ERR, "tsm: malloc failure\n");
378
0
        return SNMPERR_GENERR;
379
0
    }
380
0
    parms->pdu->transport_data_length = sizeof(*tmStateRef);
381
382
0
    DEBUGMSGTL(("tsm", "TSM processing completed.\n"));
383
0
    return SNMPERR_SUCCESS;
384
0
}
385
386
/****************************************************************************
387
 *
388
 * tsm_process_in_msg
389
 *
390
 * Parameters:
391
 *  (See list below...)
392
 *
393
 * Returns:
394
 *  TSM_ERR_NO_ERROR                        On success.
395
 *  TSM_ERR_GENERIC_ERROR
396
 *  TSM_ERR_UNSUPPORTED_SECURITY_LEVEL
397
 *
398
 *
399
 * Processes an incoming message.
400
 *
401
 ****************************************************************************/
402
403
int
404
tsm_process_in_msg(struct snmp_secmod_incoming_params *parms)
405
0
{
406
0
    u_char type_value;
407
0
    size_t remaining;
408
0
    u_char *data_ptr;
409
0
    netsnmp_tmStateReference *tmStateRef;
410
0
    netsnmp_tsmSecurityReference *tsmSecRef;
411
0
    u_char          ourEngineID[SNMP_MAX_ENG_SIZE];
412
0
    static size_t   ourEngineID_len = sizeof(ourEngineID);
413
    
414
    /* Section 5.2, step 1: Set the securityEngineID to the local
415
       snmpEngineID. */
416
0
    ourEngineID_len =
417
0
        snmpv3_get_engineID((u_char*) ourEngineID, ourEngineID_len);
418
0
    netsnmp_assert_or_return(ourEngineID_len != 0 &&
419
0
                             ourEngineID_len <= *parms->secEngineIDLen,
420
0
                             SNMPERR_GENERR);
421
0
    memcpy(parms->secEngineID, ourEngineID, *parms->secEngineIDLen);
422
423
    /* Section 5.2, step 2: If tmStateReference does not refer to a
424
       cache containing values for tmTransportDomain,
425
       tmTransportAddress, tmSecurityName, and
426
       tmTransportSecurityLevel, then the snmpTsmInvalidCaches counter
427
       is incremented, an error indication is returned to the calling
428
       module, and Security Model processing stops for this
429
       message. */
430
0
    if (!parms->pdu->transport_data ||
431
0
        sizeof(netsnmp_tmStateReference) !=
432
0
        parms->pdu->transport_data_length) {
433
        /* if we're not coming in over a proper transport; bail! */
434
0
        DEBUGMSGTL(("tsm","improper transport data\n"));
435
0
        return -1;
436
0
    }
437
0
    tmStateRef = (netsnmp_tmStateReference *) parms->pdu->transport_data;
438
0
    parms->pdu->transport_data = NULL;
439
440
0
    if (tmStateRef == NULL ||
441
        /* not needed: tmStateRef->transportDomain == NULL || */
442
        /* not needed: tmStateRef->transportAddress == NULL || */
443
0
        tmStateRef->securityName[0] == '\0'
444
0
        ) {
445
0
        snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDCACHES);
446
0
        return SNMPERR_GENERR;
447
0
    }
448
449
    /* Section 5.2, step 3: Copy the tmSecurityName to securityName. */
450
0
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
451
0
                               NETSNMP_DS_LIB_TSM_USE_PREFIX)) {
452
        /* Section 5.2, step 3:
453
          If the snmpTsmConfigurationUsePrefix object is set to true, then
454
          use the tmTransportDomain to look up the corresponding prefix.
455
        */
456
0
        const char *prefix = NULL;
457
        /*
458
          possibilities:
459
           |--------------------+-------|
460
           | snmpTLSTCPDomain   | tls:  |
461
           | snmpDTLSUDPDomain  | dtls: |
462
           | snmpSSHDomain      | ssh:  |
463
           |--------------------+-------|
464
        */
465
        
466
        /* XXX: cache in session! */
467
#ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
468
        if (netsnmp_oid_equals(netsnmp_snmpSSHDomain,
469
                               netsnmp_snmpSSHDomain_len,
470
                               tmStateRef->transportDomain,
471
                               tmStateRef->transportDomainLen) == 0) {
472
            prefix = "ssh";
473
        }
474
#endif /*  NETSNMP_TRANSPORT_SSH_DOMAIN */
475
476
0
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
477
0
        if (netsnmp_oid_equals(netsnmpDTLSUDPDomain,
478
0
                               netsnmpDTLSUDPDomain_len,
479
0
                               tmStateRef->transportDomain,
480
0
                               tmStateRef->transportDomainLen) == 0) {
481
            
482
0
            prefix = "dtls";
483
0
        }
484
0
#endif /* NETSNMP_TRANSPORT_DTLSUDP_DOMAIN */
485
486
0
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
487
0
        if (netsnmp_oid_equals(netsnmpTLSTCPDomain,
488
0
                               netsnmpTLSTCPDomain_len,
489
0
                               tmStateRef->transportDomain,
490
0
                               tmStateRef->transportDomainLen) == 0) {
491
            
492
0
            prefix = "tls";
493
0
        }
494
0
#endif /* NETSNMP_TRANSPORT_TLSTCP_DOMAIN */
495
496
        /* Section 5.2, step 3:
497
          If the prefix lookup fails for any reason, then the
498
          snmpTsmUnknownPrefixes counter is incremented, an error
499
          indication is returned to the calling module, and message
500
          processing stops.
501
        */
502
0
        if (prefix == NULL) {
503
0
            snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES);
504
0
            return SNMPERR_GENERR;
505
0
        }
506
507
        /* Section 5.2, step 3:
508
          If the lookup succeeds but the prefix length is less than 1 or
509
          greater than 4 octets, then the snmpTsmInvalidPrefixes counter
510
          is incremented, an error indication is returned to the calling
511
          module, and message processing stops.
512
        */
513
#ifdef NOT_USING_HARDCODED_PREFIXES
514
        /* the above code actually ensures this will never happen as
515
           we don't support a dynamic prefix database where this might
516
           happen. */
517
        if (strlen(prefix) < 1 || strlen(prefix) > 4) {
518
            /* XXX: snmpTsmInvalidPrefixes++ */
519
            return SNMPERR_GENERR;
520
        }
521
#endif
522
        
523
        /* Section 5.2, step 3:
524
          Set the securityName to be the concatenation of the prefix, a
525
          ':' character (US-ASCII 0x3a), and the tmSecurityName.
526
        */
527
0
        snprintf(parms->secName, *parms->secNameLen,
528
0
                 "%s:%s", prefix, tmStateRef->securityName);
529
0
    } else {
530
        /* if the use prefix flag wasn't set, do a straight copy */
531
0
        strncpy(parms->secName, tmStateRef->securityName, *parms->secNameLen);
532
0
    }
533
534
    /* set the length of the security name */
535
0
    *parms->secNameLen = strlen(parms->secName);
536
0
    DEBUGMSGTL(("tsm", "user: %s/%d\n", parms->secName, (int)*parms->secNameLen));
537
538
    /* Section 5.2 Step 4:
539
       Compare the value of tmTransportSecurityLevel in the
540
       tmStateReference cache to the value of the securityLevel
541
       parameter passed in the processIncomingMsg ASI.  If securityLevel
542
       specifies privacy (Priv) and tmTransportSecurityLevel specifies
543
       no privacy (noPriv), or if securityLevel specifies authentication
544
       (auth) and tmTransportSecurityLevel specifies no authentication
545
       (noAuth) was provided by the Transport Model, then the
546
       snmpTsmInadequateSecurityLevels counter is incremented, an error
547
       indication (unsupportedSecurityLevel) together with the OID and
548
       value of the incremented counter is returned to the calling
549
       module, and Transport Security Model processing stops for this
550
       message.*/
551
0
    if (parms->secLevel > tmStateRef->transportSecurityLevel) {
552
0
        snmp_increment_statistic(STAT_TSM_SNMPTSMINADEQUATESECURITYLEVELS);
553
0
        DEBUGMSGTL(("tsm", "inadequate security level: %d\n", parms->secLevel));
554
        /* net-snmp returns error codes not OIDs, which are dealt with later */
555
0
        return SNMPERR_UNSUPPORTED_SEC_LEVEL;
556
0
    }
557
558
    /* Section 5.2 Step 5
559
       The tmStateReference is cached as cachedSecurityData so that a
560
       possible response to this message will use the same security
561
       parameters.  Then securityStateReference is set for subsequent
562
       references to this cached data.
563
    */
564
0
    if (NULL == *parms->secStateRef) {
565
0
        tsmSecRef = SNMP_MALLOC_TYPEDEF(netsnmp_tsmSecurityReference);
566
0
    } else {
567
0
        tsmSecRef = *parms->secStateRef;
568
0
    }
569
570
0
    netsnmp_assert_or_return(NULL != tsmSecRef, SNMPERR_GENERR);
571
572
0
    *parms->secStateRef = tsmSecRef;
573
0
    tsmSecRef->tmStateRef = tmStateRef;
574
575
    /* If this did not come through a tunneled connection, this
576
       security model is inappropriate (and would be a HUGE security
577
       hole to assume otherwise).  This is functionally a double check
578
       since the pdu wouldn't have transport data otherwise.  But this
579
       is safer though is functionally an extra step beyond the TSM
580
       RFC. */
581
0
    DEBUGMSGTL(("tsm","checking how we got here\n"));
582
0
    if (!(parms->pdu->flags & UCD_MSG_FLAG_TUNNELED)) {
583
0
        DEBUGMSGTL(("tsm","  pdu not tunneled\n"));
584
0
        if (!(parms->sess->flags & NETSNMP_TRANSPORT_FLAG_TUNNELED)) {
585
0
            DEBUGMSGTL(("tsm","  session not tunneled\n"));
586
0
            return SNMPERR_USM_AUTHENTICATIONFAILURE;
587
0
        }
588
0
        DEBUGMSGTL(("tsm","  but session is tunneled\n"));
589
0
    } else {
590
0
        DEBUGMSGTL(("tsm","  tunneled\n"));
591
0
    }
592
593
    /* Section 5.2, Step 6:
594
       The scopedPDU component is extracted from the wholeMsg. */
595
    /*
596
     * Eat the first octet header.
597
     */
598
0
    remaining = parms->wholeMsgLen - (parms->secParams - parms->wholeMsg);
599
0
    if ((data_ptr = asn_parse_sequence(parms->secParams, &remaining,
600
0
                                        &type_value,
601
0
                                        (ASN_UNIVERSAL | ASN_PRIMITIVE |
602
0
                                         ASN_OCTET_STR),
603
0
                                        "tsm first octet")) == NULL) {
604
        /*
605
         * RETURN parse error 
606
         */
607
0
        return SNMPERR_ASN_PARSE_ERR;
608
0
    }
609
    
610
0
    *parms->scopedPdu = data_ptr;
611
0
    *parms->scopedPduLen = parms->wholeMsgLen - (data_ptr - parms->wholeMsg);
612
613
    /* Section 5.2, Step 7:
614
       The maxSizeResponseScopedPDU is calculated.  This is the maximum
615
       size allowed for a scopedPDU for a possible Response message.
616
     */
617
0
    *parms->maxSizeResponse = parms->maxMsgSize; /* XXX */
618
619
    /* Section 5.2, Step 8:
620
       The statusInformation is set to success and a return is made to
621
       the calling module passing back the OUT parameters as specified
622
       in the processIncomingMsg ASI.
623
    */
624
0
    return SNMPERR_SUCCESS;
625
0
}