net-snmp 5.7
snmptsm.c
00001 /*
00002  * snmptsmsm.c -- Implements RFC #5591
00003  *
00004  * This code implements a security model that assumes the local user
00005  * that executed the agent is the user who's attributes are passed up
00006  * by the transport underneath.  The RFC describing this security
00007  * model is RFC5591.
00008  */
00009 
00010 #include <net-snmp/net-snmp-config.h>
00011 
00012 #include <net-snmp/net-snmp-features.h>
00013 #include <net-snmp/net-snmp-includes.h>
00014 
00015 #include <net-snmp/library/snmptsm.h>
00016 
00017 #ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
00018 #include <net-snmp/library/snmpSSHDomain.h>
00019 #endif
00020 #ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
00021 #include <net-snmp/library/snmpDTLSUDPDomain.h>
00022 #endif
00023 #ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
00024 #include <net-snmp/library/snmpTLSTCPDomain.h>
00025 #endif
00026 #ifdef NETSNMP_TRANSPORT_DTLSSCTP_DOMAIN
00027 #include <net-snmp/library/snmpDTLSSCTPDomain.h>
00028 #endif
00029 
00030 netsnmp_feature_require(snmpv3_probe_contextEngineID_rfc5343)
00031 netsnmp_feature_require(row_create)
00032 
00033 #include <unistd.h>
00034 
00035 static int      tsm_session_init(netsnmp_session *);
00036 static void     tsm_free_state_ref(void *);
00037 static int      tsm_clone_pdu(netsnmp_pdu *, netsnmp_pdu *);
00038 static int      tsm_free_pdu(netsnmp_pdu *pdu);
00039 
00040 u_int next_sess_id = 1;
00041 
00043 void
00044 init_tsm(void)
00045 {
00046     struct snmp_secmod_def *def;
00047     int ret;
00048 
00049     def = SNMP_MALLOC_STRUCT(snmp_secmod_def);
00050 
00051     if (!def) {
00052         snmp_log(LOG_ERR,
00053                  "Unable to malloc snmp_secmod struct, not registering TSM\n");
00054         return;
00055     }
00056 
00057     def->encode_reverse = tsm_rgenerate_out_msg;
00058     def->decode = tsm_process_in_msg;
00059     def->session_open = tsm_session_init;
00060     def->pdu_free_state_ref = tsm_free_state_ref;
00061     def->pdu_clone = tsm_clone_pdu;
00062     def->pdu_free = tsm_free_pdu;
00063     def->probe_engineid = snmpv3_probe_contextEngineID_rfc5343;
00064 
00065     DEBUGMSGTL(("tsm","registering ourselves\n"));
00066     ret = register_sec_mod(SNMP_SEC_MODEL_TSM, "tsm", def);
00067     DEBUGMSGTL(("tsm"," returned %d\n", ret));
00068 
00069     netsnmp_ds_register_config(ASN_BOOLEAN, "snmp", "tsmUseTransportPrefix",
00070                                NETSNMP_DS_LIBRARY_ID,
00071                                NETSNMP_DS_LIB_TSM_USE_PREFIX);
00072 }
00073 
00075 void
00076 shutdown_tsm(void)
00077 {
00078 }
00079 
00080 /*
00081  * Initialize specific session information (right now, just set up things to
00082  * not do an engineID probe)
00083  */
00084 
00085 static int
00086 tsm_session_init(netsnmp_session * sess)
00087 {
00088     DEBUGMSGTL(("tsm",
00089                 "TSM: Reached our session initialization callback\n"));
00090 
00091     sess->flags |= SNMP_FLAGS_DONT_PROBE;
00092 
00093     /* XXX: likely needed for something: */
00094     /*
00095     tsmsession = sess->securityInfo =
00096     if (!tsmsession)
00097         return SNMPERR_GENERR;
00098     */
00099 
00100     return SNMPERR_SUCCESS;
00101 }
00102 
00104 static void
00105 tsm_free_state_ref(void *ptr)
00106 {
00107     netsnmp_tsmSecurityReference *tsmRef;
00108 
00109     if (NULL == ptr)
00110         return;
00111 
00112     tsmRef = (netsnmp_tsmSecurityReference *) ptr;
00113     /* the tmStateRef is always taken care of by the normal PDU, since this
00114        is just a reference to that one */
00115     /* DON'T DO: SNMP_FREE(tsmRef->tmStateRef); */
00116     /* SNMP_FREE(tsmRef);  ? */
00117 }
00118 
00119 static int
00120 tsm_free_pdu(netsnmp_pdu *pdu)
00121 {
00122     /* free the security reference */
00123     if (pdu->securityStateRef) {
00124         tsm_free_state_ref(pdu->securityStateRef);
00125         pdu->securityStateRef = NULL;
00126     }
00127     return 0;
00128 }
00129 
00131 static int
00132 tsm_clone_pdu(netsnmp_pdu *pdu, netsnmp_pdu *pdu2)
00133 {
00134     netsnmp_tsmSecurityReference *oldref, *newref;
00135 
00136     oldref = pdu->securityStateRef;
00137     if (!oldref)
00138         return SNMPERR_SUCCESS;
00139 
00140     newref = SNMP_MALLOC_TYPEDEF(netsnmp_tsmSecurityReference);
00141     DEBUGMSGTL(("tsm", "cloned as pdu=%p, ref=%p (oldref=%p)\n",
00142             pdu2, newref, pdu2->securityStateRef));
00143     if (!newref)
00144         return SNMPERR_GENERR;
00145     
00146     memcpy(newref, oldref, sizeof(*oldref));
00147 
00148     pdu2->securityStateRef = newref;
00149 
00150     /* the tm state reference is just a link to the one in the pdu,
00151        which was already copied by snmp_clone_pdu before handing it to
00152        us. */
00153 
00154     memdup((u_char **) &newref->tmStateRef, oldref->tmStateRef,
00155            sizeof(*oldref->tmStateRef));
00156     return SNMPERR_SUCCESS;
00157 }
00158 
00159 /* asn.1 easing definitions */
00160 #define TSMBUILD_OR_ERR(fun, args, msg, desc)       \
00161     DEBUGDUMPHEADER("send", desc); \
00162     rc = fun args;            \
00163     DEBUGINDENTLESS();        \
00164     if (rc == 0) { \
00165         DEBUGMSGTL(("tsm",msg)); \
00166         retval = SNMPERR_TOO_LONG; \
00167         goto outerr; \
00168     }
00169 
00170 /****************************************************************************
00171  *
00172  * tsm_generate_out_msg
00173  *
00174  * Parameters:
00175  *      (See list below...)
00176  *
00177  * Returns:
00178  *      SNMPERR_SUCCESS                        On success.
00179  *      ... and others
00180  *
00181  *
00182  * Generate an outgoing message.
00183  *
00184  ****************************************************************************/
00185 
00186 int
00187 tsm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
00188 {
00189     u_char         **wholeMsg = parms->wholeMsg;
00190     size_t         *offset = parms->wholeMsgOffset;
00191     int rc;
00192     
00193     size_t         *wholeMsgLen = parms->wholeMsgLen;
00194     netsnmp_tsmSecurityReference *tsmSecRef;
00195     netsnmp_tmStateReference *tmStateRef;
00196     
00197     DEBUGMSGTL(("tsm", "Starting TSM processing\n"));
00198 
00199     /* if we have this, then this message to be sent is in response to
00200        something that came in earlier and the tsmSecRef was created by
00201        the tsm_process_in_msg. */
00202     tsmSecRef = parms->secStateRef;
00203     
00204     if (tsmSecRef) {
00205         /* 4.2, step 1: If there is a securityStateReference (Response
00206            or Report message), then this Security Model uses the
00207            cached information rather than the information provided by
00208            the ASI. */
00209 
00210         /* 4.2, step 1: Extract the tmStateReference from the
00211            securityStateReference cache. */
00212         netsnmp_assert_or_return(NULL != tsmSecRef->tmStateRef, SNMPERR_GENERR);
00213         tmStateRef = tsmSecRef->tmStateRef;
00214 
00215         /* 4.2 step 1: Set the tmRequestedSecurityLevel to the value
00216            of the extracted tmTransportSecurityLevel. */
00217         tmStateRef->requestedSecurityLevel = tmStateRef->transportSecurityLevel;
00218 
00219         /* 4.2 step 1: Set the tmSameSecurity parameter in the
00220            tmStateReference cache to true. */
00221         tmStateRef->sameSecurity = NETSNMP_TM_USE_SAME_SECURITY;
00222 
00223         /* 4.2 step 1: The cachedSecurityData for this message can
00224            now be discarded. */
00225         SNMP_FREE(parms->secStateRef);
00226     } else {
00227         /* 4.2, step 2: If there is no securityStateReference (e.g., a
00228            Request-type or Notification message), then create a
00229            tmStateReference cache. */
00230         tmStateRef = SNMP_MALLOC_TYPEDEF(netsnmp_tmStateReference);
00231         netsnmp_assert_or_return(NULL != tmStateRef, SNMPERR_GENERR);
00232         
00233         /* XXX: we don't actually use this really in our implementation */
00234         /* 4.2, step 2: Set tmTransportDomain to the value of
00235            transportDomain, tmTransportAddress to the value of
00236            transportAddress */
00237 
00238         /* 4.2, step 2: and tmRequestedSecurityLevel to the value of
00239            securityLevel. */
00240         tmStateRef->requestedSecurityLevel = parms->secLevel;
00241 
00242         /* 4.2, step 2: Set the transaction-specific tmSameSecurity
00243            parameter to false. */
00244         tmStateRef->sameSecurity = NETSNMP_TM_SAME_SECURITY_NOT_REQUIRED;
00245 
00246         if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00247                                    NETSNMP_DS_LIB_TSM_USE_PREFIX)) {
00248             /* XXX: probably shouldn't be a hard-coded list of
00249                supported transports */
00250             /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix
00251                object is set to true, then use the transportDomain to
00252                look up the corresponding prefix. */
00253             const char *prefix;
00254             if (strncmp("ssh:",parms->session->peername,4) == 0)
00255                 prefix = "ssh:";
00256             else if (strncmp("dtls:",parms->session->peername,5) == 0)
00257                 prefix = "dtls:";
00258             else if (strncmp("tls:",parms->session->peername,4) == 0)
00259                 prefix = "tls:";
00260             else {
00261                 /* 4.2, step 2: If the prefix lookup fails for any
00262                    reason, then the snmpTsmUnknownPrefixes counter is
00263                    incremented, an error indication is returned to the
00264                    calling module, and message processing stops. */
00265                 snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES);
00266                 return SNMPERR_GENERR;
00267             }
00268 
00269             /* 4.2, step 2: If the lookup succeeds, but there is no
00270                prefix in the securityName, or the prefix returned does
00271                not match the prefix in the securityName, or the length
00272                of the prefix is less than 1 or greater than 4 US-ASCII
00273                alpha-numeric characters, then the
00274                snmpTsmInvalidPrefixes counter is incremented, an error
00275                indication is returned to the calling module, and
00276                message processing stops. */
00277             if (strchr(parms->secName, ':') == 0 ||
00278                 strlen(prefix)+1 >= parms->secNameLen ||
00279                 strncmp(parms->secName, prefix, strlen(prefix)) != 0 ||
00280                 parms->secName[strlen(prefix)] != ':') {
00281                 /* Note: since we're assiging the prefixes above the
00282                    prefix lengths always meet the 1-4 criteria */
00283                 snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDPREFIXES);
00284                 return SNMPERR_GENERR;
00285             }
00286 
00287             /* 4.2, step 2: Strip the transport-specific prefix and
00288                trailing ':' character (US-ASCII 0x3a) from the
00289                securityName.  Set tmSecurityName to the value of
00290                securityName. */
00291             memcpy(tmStateRef->securityName,
00292                    parms->secName + strlen(prefix) + 1,
00293                    parms->secNameLen - strlen(prefix) - 1);
00294             tmStateRef->securityNameLen = parms->secNameLen - strlen(prefix) -1;
00295         } else {
00296             /* 4.2, step 2: If the snmpTsmConfigurationUsePrefix object is
00297                set to false, then set tmSecurityName to the value
00298                of securityName. */
00299             memcpy(tmStateRef->securityName, parms->secName,
00300                    parms->secNameLen);
00301             tmStateRef->securityNameLen = parms->secNameLen;
00302         }
00303     }
00304 
00305     /* truncate the security name with a '\0' for safety */
00306     tmStateRef->securityName[tmStateRef->securityNameLen] = '\0';
00307 
00308     /* 4.2, step 3: Set securityParameters to a zero-length OCTET
00309      *  STRING ('0400').
00310      */
00311     DEBUGDUMPHEADER("send", "tsm security parameters");
00312     rc = asn_realloc_rbuild_header(wholeMsg, wholeMsgLen, offset, 1,
00313                                      (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE
00314                                              | ASN_OCTET_STR), 0);
00315     DEBUGINDENTLESS();
00316     if (rc == 0) {
00317         DEBUGMSGTL(("tsm", "building msgSecurityParameters failed.\n"));
00318         return SNMPERR_TOO_LONG;
00319     }
00320     
00321     /* 4.2, step 4: Combine the message parts into a wholeMsg and
00322        calculate wholeMsgLength.
00323      */
00324     while ((*wholeMsgLen - *offset) < parms->globalDataLen) {
00325         if (!asn_realloc(wholeMsg, wholeMsgLen)) {
00326             DEBUGMSGTL(("tsm", "building global data failed.\n"));
00327             return SNMPERR_TOO_LONG;
00328         }
00329     }
00330 
00331     *offset += parms->globalDataLen;
00332     memcpy(*wholeMsg + *wholeMsgLen - *offset,
00333            parms->globalData, parms->globalDataLen);
00334 
00335     /* 4.2, step 5: The wholeMsg, wholeMsgLength, securityParameters,
00336        and tmStateReference are returned to the calling Message
00337        Processing Model with the statusInformation set to success. */
00338 
00339     /* For the Net-SNMP implemantion that actually means we start
00340        encoding the full packet sequence from here before returning it */
00341 
00342     /*
00343      * Total packet sequence.  
00344      */
00345     rc = asn_realloc_rbuild_sequence(wholeMsg, wholeMsgLen, offset, 1,
00346                                      (u_char) (ASN_SEQUENCE |
00347                                                ASN_CONSTRUCTOR), *offset);
00348     if (rc == 0) {
00349         DEBUGMSGTL(("tsm", "building master packet sequence failed.\n"));
00350         return SNMPERR_TOO_LONG;
00351     }
00352 
00353     if (parms->pdu->transport_data &&
00354         parms->pdu->transport_data != tmStateRef) {
00355         snmp_log(LOG_ERR, "tsm: needed to free transport data\n");
00356         SNMP_FREE(parms->pdu->transport_data);
00357     }
00358 
00359     /* put the transport state reference into the PDU for the transport */
00360     if (SNMPERR_SUCCESS !=
00361         memdup((u_char **) &parms->pdu->transport_data,
00362                tmStateRef, sizeof(*tmStateRef))) {
00363         snmp_log(LOG_ERR, "tsm: malloc failure\n");
00364     }
00365     parms->pdu->transport_data_length = sizeof(*tmStateRef);
00366 
00367     DEBUGMSGTL(("tsm", "TSM processing completed.\n"));
00368     return SNMPERR_SUCCESS;
00369 }
00370 
00371 /****************************************************************************
00372  *
00373  * tsm_process_in_msg
00374  *
00375  * Parameters:
00376  *      (See list below...)
00377  *
00378  * Returns:
00379  *      TSM_ERR_NO_ERROR                        On success.
00380  *      TSM_ERR_GENERIC_ERROR
00381  *      TSM_ERR_UNSUPPORTED_SECURITY_LEVEL
00382  *
00383  *
00384  * Processes an incoming message.
00385  *
00386  ****************************************************************************/
00387 
00388 int
00389 tsm_process_in_msg(struct snmp_secmod_incoming_params *parms)
00390 {
00391     u_char type_value;
00392     size_t remaining;
00393     u_char *data_ptr;
00394     netsnmp_tmStateReference *tmStateRef;
00395     netsnmp_tsmSecurityReference *tsmSecRef;
00396     u_char          ourEngineID[SNMP_MAX_ENG_SIZE];
00397     static size_t   ourEngineID_len = sizeof(ourEngineID);
00398     
00399     /* Section 5.2, step 1: Set the securityEngineID to the local
00400        snmpEngineID. */
00401     ourEngineID_len =
00402         snmpv3_get_engineID((u_char*) ourEngineID, ourEngineID_len);
00403     netsnmp_assert_or_return(ourEngineID_len != 0 &&
00404                              ourEngineID_len <= *parms->secEngineIDLen,
00405                              SNMPERR_GENERR);
00406     memcpy(parms->secEngineID, ourEngineID, *parms->secEngineIDLen);
00407 
00408     /* Section 5.2, step 2: If tmStateReference does not refer to a
00409        cache containing values for tmTransportDomain,
00410        tmTransportAddress, tmSecurityName, and
00411        tmTransportSecurityLevel, then the snmpTsmInvalidCaches counter
00412        is incremented, an error indication is returned to the calling
00413        module, and Security Model processing stops for this
00414        message. */
00415     if (!parms->pdu->transport_data ||
00416         sizeof(netsnmp_tmStateReference) !=
00417         parms->pdu->transport_data_length) {
00418         /* if we're not coming in over a proper transport; bail! */
00419         DEBUGMSGTL(("tsm","improper transport data\n"));
00420         return -1;
00421     }
00422     tmStateRef = (netsnmp_tmStateReference *) parms->pdu->transport_data;
00423     parms->pdu->transport_data = NULL;
00424 
00425     if (tmStateRef == NULL ||
00426         /* not needed: tmStateRef->transportDomain == NULL || */
00427         /* not needed: tmStateRef->transportAddress == NULL || */
00428         tmStateRef->securityName[0] == '\0'
00429         ) {
00430         snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDCACHES);
00431         return SNMPERR_GENERR;
00432     }
00433 
00434     /* Section 5.2, step 3: Copy the tmSecurityName to securityName. */
00435     if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00436                                NETSNMP_DS_LIB_TSM_USE_PREFIX)) {
00437         /* Section 5.2, step 3:
00438           If the snmpTsmConfigurationUsePrefix object is set to true, then
00439           use the tmTransportDomain to look up the corresponding prefix.
00440         */
00441         const char *prefix = NULL;
00442         /*
00443           possibilities:
00444            |--------------------+-------|
00445            | snmpTLSTCPDomain   | tls:  |
00446            | snmpDTLSUDPDomain  | dtls: |
00447            | snmpSSHDomain      | ssh:  |
00448            |--------------------+-------|
00449         */
00450         
00451         if (tmStateRef->transportDomain == NULL) {
00452             /* XXX: snmpTsmInvalidCaches++ ??? */
00453             return SNMPERR_GENERR;
00454         }
00455 
00456         /* XXX: cache in session! */
00457 #ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
00458         if (netsnmp_oid_equals(netsnmp_snmpSSHDomain,
00459                                netsnmp_snmpSSHDomain_len,
00460                                tmStateRef->transportDomain,
00461                                tmStateRef->transportDomainLen) == 0) {
00462             prefix = "ssh";
00463         }
00464 #endif /*  NETSNMP_TRANSPORT_SSH_DOMAIN */
00465 
00466 #ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
00467         if (netsnmp_oid_equals(netsnmpDTLSUDPDomain,
00468                                netsnmpDTLSUDPDomain_len,
00469                                tmStateRef->transportDomain,
00470                                tmStateRef->transportDomainLen) == 0) {
00471             
00472             prefix = "dtls";
00473         }
00474 #endif /* NETSNMP_TRANSPORT_DTLSUDP_DOMAIN */
00475 
00476 #ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
00477         if (netsnmp_oid_equals(netsnmpTLSTCPDomain,
00478                                netsnmpTLSTCPDomain_len,
00479                                tmStateRef->transportDomain,
00480                                tmStateRef->transportDomainLen) == 0) {
00481             
00482             prefix = "tls";
00483         }
00484 #endif /* NETSNMP_TRANSPORT_TLSTCP_DOMAIN */
00485 
00486         /* Section 5.2, step 3:
00487           If the prefix lookup fails for any reason, then the
00488           snmpTsmUnknownPrefixes counter is incremented, an error
00489           indication is returned to the calling module, and message
00490           processing stops.
00491         */
00492         if (prefix == NULL) {
00493             snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES);
00494             return SNMPERR_GENERR;
00495         }
00496 
00497         /* Section 5.2, step 3:
00498           If the lookup succeeds but the prefix length is less than 1 or
00499           greater than 4 octets, then the snmpTsmInvalidPrefixes counter
00500           is incremented, an error indication is returned to the calling
00501           module, and message processing stops.
00502         */
00503 #ifdef NOT_USING_HARDCODED_PREFIXES
00504         /* the above code actually ensures this will never happen as
00505            we don't support a dynamic prefix database where this might
00506            happen. */
00507         if (strlen(prefix) < 1 || strlen(prefix) > 4) {
00508             /* XXX: snmpTsmInvalidPrefixes++ */
00509             return SNMPERR_GENERR;
00510         }
00511 #endif
00512         
00513         /* Section 5.2, step 3:
00514           Set the securityName to be the concatenation of the prefix, a
00515           ':' character (US-ASCII 0x3a), and the tmSecurityName.
00516         */
00517         snprintf(parms->secName, *parms->secNameLen,
00518                  "%s:%s", prefix, tmStateRef->securityName);
00519     } else {
00520         /* if the use prefix flag wasn't set, do a straight copy */
00521         strncpy(parms->secName, tmStateRef->securityName, *parms->secNameLen);
00522     }
00523 
00524     /* set the length of the security name */
00525     *parms->secNameLen = strlen(parms->secName);
00526     DEBUGMSGTL(("tsm", "user: %s/%d\n", parms->secName, (int)*parms->secNameLen));
00527 
00528     /* Section 5.2 Step 4:
00529        Compare the value of tmTransportSecurityLevel in the
00530        tmStateReference cache to the value of the securityLevel
00531        parameter passed in the processIncomingMsg ASI.  If securityLevel
00532        specifies privacy (Priv) and tmTransportSecurityLevel specifies
00533        no privacy (noPriv), or if securityLevel specifies authentication
00534        (auth) and tmTransportSecurityLevel specifies no authentication
00535        (noAuth) was provided by the Transport Model, then the
00536        snmpTsmInadequateSecurityLevels counter is incremented, an error
00537        indication (unsupportedSecurityLevel) together with the OID and
00538        value of the incremented counter is returned to the calling
00539        module, and Transport Security Model processing stops for this
00540        message.*/
00541     if (parms->secLevel > tmStateRef->transportSecurityLevel) {
00542         snmp_increment_statistic(STAT_TSM_SNMPTSMINADEQUATESECURITYLEVELS);
00543         DEBUGMSGTL(("tsm", "inadequate security level: %d\n", parms->secLevel));
00544         /* net-snmp returns error codes not OIDs, which are dealt with later */
00545         return SNMPERR_UNSUPPORTED_SEC_LEVEL;
00546     }
00547 
00548     /* Section 5.2 Step 5
00549        The tmStateReference is cached as cachedSecurityData so that a
00550        possible response to this message will use the same security
00551        parameters.  Then securityStateReference is set for subsequent
00552        references to this cached data.
00553     */
00554     if (NULL == *parms->secStateRef) {
00555         tsmSecRef = SNMP_MALLOC_TYPEDEF(netsnmp_tsmSecurityReference);
00556     } else {
00557         tsmSecRef = *parms->secStateRef;
00558     }
00559 
00560     netsnmp_assert_or_return(NULL != tsmSecRef, SNMPERR_GENERR);
00561 
00562     *parms->secStateRef = tsmSecRef;
00563     tsmSecRef->tmStateRef = tmStateRef;
00564 
00565     /* If this did not come through a tunneled connection, this
00566        security model is inappropriate (and would be a HUGE security
00567        hole to assume otherwise).  This is functionally a double check
00568        since the pdu wouldn't have transport data otherwise.  But this
00569        is safer though is functionally an extra step beyond the TSM
00570        RFC. */
00571     DEBUGMSGTL(("tsm","checking how we got here\n"));
00572     if (!(parms->pdu->flags & UCD_MSG_FLAG_TUNNELED)) {
00573         DEBUGMSGTL(("tsm","  pdu not tunneled\n"));
00574         if (!(parms->sess->flags & NETSNMP_TRANSPORT_FLAG_TUNNELED)) {
00575             DEBUGMSGTL(("tsm","  session not tunneled\n"));
00576             return SNMPERR_USM_AUTHENTICATIONFAILURE;
00577         }
00578         DEBUGMSGTL(("tsm","  but session is tunneled\n"));
00579     } else {
00580         DEBUGMSGTL(("tsm","  tunneled\n"));
00581     }
00582 
00583     /* Section 5.2, Step 6:
00584        The scopedPDU component is extracted from the wholeMsg. */
00585     /*
00586      * Eat the first octet header.
00587      */
00588     remaining = parms->wholeMsgLen - (parms->secParams - parms->wholeMsg);
00589     if ((data_ptr = asn_parse_sequence(parms->secParams, &remaining,
00590                                         &type_value,
00591                                         (ASN_UNIVERSAL | ASN_PRIMITIVE |
00592                                          ASN_OCTET_STR),
00593                                         "tsm first octet")) == NULL) {
00594         /*
00595          * RETURN parse error 
00596          */
00597         return SNMPERR_ASN_PARSE_ERR;
00598     }
00599     
00600     *parms->scopedPdu = data_ptr;
00601     *parms->scopedPduLen = parms->wholeMsgLen - (data_ptr - parms->wholeMsg);
00602 
00603     /* Section 5.2, Step 7:
00604        The maxSizeResponseScopedPDU is calculated.  This is the maximum
00605        size allowed for a scopedPDU for a possible Response message.
00606      */
00607     *parms->maxSizeResponse = parms->maxMsgSize; /* XXX */
00608 
00609     /* Section 5.2, Step 8:
00610        The statusInformation is set to success and a return is made to
00611        the calling module passing back the OUT parameters as specified
00612        in the processIncomingMsg ASI.
00613     */
00614     return SNMPERR_SUCCESS;
00615 }