# ldap.cnf # LDAP conformation file # Copyright 2005 Anders Broman # $Id$ #.PDU LDAPMessage #.TYPE_RENAME BindResponse/resultCode BindResponse_resultCode ExtendedResponse/resultCode ExtendedResponse_resultCode ModifyRequest/modification ModifyRequest_modification #.FIELD_RENAME BindResponse/resultCode bindResponse_resultCode ExtendedResponse/resultCode extendedResponse_resultCode SearchRequest/attributes searchRequest_attributes SearchResultEntry/attributes searchResultEntry_attributes ModifyRequest/modification modifyRequest_modification SubstringFilter/substrings substringFilter_substrings #.TYPE_ATTR LDAPString TYPE = FT_STRING DISPLAY = BASE_NONE STRINGS = NULL LDAPURL TYPE = FT_STRING DISPLAY = BASE_NONE STRINGS = NULL LDAPOID TYPE = FT_STRING DISPLAY = BASE_NONE STRINGS = NULL Mechanism TYPE = FT_STRING DISPLAY = BASE_NONE STRINGS = NULL AssertionValue TYPE = FT_STRING DISPLAY = BASE_NONE STRINGS = NULL #.FN_PARS LDAPOID VAL_PTR = ¶meter_tvb #.FN_HDR LDAPOID tvbuff_t *parameter_tvb; const gchar *name; proto_item *item = NULL; #.FN_FTR LDAPOID if (!parameter_tvb) return offset; item = get_ber_last_created_item(); name = get_oid_str_name(tvb_get_string(parameter_tvb, 0, tvb_length_remaining(parameter_tvb,0))); if(name){ proto_item_append_text(item, " (%s)", name); proto_item_append_text(tree, " %s", name); } #.FN_PARS MessageID VAL_PTR = &MessageID #.FN_BODY MessageID %(DEFAULT_BODY)s ldm_tree = tree; #.FN_PARS ProtocolOp VAL_PTR = &ProtocolOp #.FN_HDR ProtocolOp ldap_call_response_t *lcrp; ldap_conv_info_t *ldap_info = (ldap_conv_info_t *)pinfo->private_data; do_protocolop = TRUE; #.FN_FTR ProtocolOp lcrp=ldap_match_call_response(tvb, pinfo, tree, MessageID, ProtocolOp); if(lcrp){ tap_queue_packet(ldap_tap, pinfo, lcrp); } /* XXX: the count will not work if the results span multiple TCP packets */ if(ldap_info && tree) { /* only count once - on tree pass */ switch(ProtocolOp) { case LDAP_RES_SEARCH_ENTRY: ldap_info->num_results++; proto_item_append_text(tree, " [%d result%s]", ldap_info->num_results, ldap_info->num_results == 1 ? "" : "s"); break; case LDAP_RES_SEARCH_RESULT: if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, " [%d result%s]", ldap_info->num_results, ldap_info->num_results == 1 ? "" : "s"); proto_item_append_text(tree, " [%d result%s]", ldap_info->num_results, ldap_info->num_results == 1 ? "" : "s"); ldap_info->num_results = 0; break; default: break; } } #.FN_BODY Simple ldap_conv_info_t *ldap_info; %(DEFAULT_BODY)s ldap_info = pinfo->private_data; ldap_info->auth_type = LDAP_AUTH_SIMPLE; pinfo->private_data = ldap_info; #.FN_PARS Mechanism VAL_PTR = ¶meter_tvb #.FN_BODY Mechanism ldap_conv_info_t *ldap_info; tvbuff_t *parameter_tvb; char *mechanism = NULL; %(DEFAULT_BODY)s ldap_info = pinfo->private_data; ldap_info->auth_type = LDAP_AUTH_SASL; if (!parameter_tvb) return offset; /* * We need to remember the authentication type and mechanism for this * conversation. * * XXX - actually, we might need to remember more than one * type and mechanism, if you can unbind and rebind with a * different type and/or mechanism. */ mechanism = tvb_get_string(parameter_tvb, 0, tvb_length_remaining(parameter_tvb,0)); ldap_info->first_auth_frame = 0; /* not known until we see the bind reply */ /* * If the mechanism in this request is an empty string (which is * returned as a null pointer), use the saved mechanism instead. * Otherwise, if the saved mechanism is an empty string (null), * save this mechanism. */ if (mechanism == NULL) mechanism = ldap_info->auth_mech; else { if (ldap_info->auth_mech == NULL) { g_free(ldap_info->auth_mech); } ldap_info->auth_mech = mechanism; } pinfo->private_data = ldap_info; #.FN_PARS Credentials VAL_PTR = ¶meter_tvb #.FN_BODY Credentials tvbuff_t *parameter_tvb; ldap_conv_info_t *ldap_info; %(DEFAULT_BODY)s if (!parameter_tvb) return offset; ldap_info = pinfo->private_data; if (ldap_info->auth_mech != NULL && strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) { /* * This is a GSS-API token ancapsulated within GSS-SPNEGO. */ if (parameter_tvb) call_dissector(gssapi_handle, parameter_tvb, pinfo, tree); } else if (ldap_info->auth_mech != NULL && strcmp(ldap_info->auth_mech, "GSSAPI") == 0) { /* * This is a raw GSS-API token. */ if (parameter_tvb) call_dissector(gssapi_handle, parameter_tvb, pinfo, tree); } pinfo->private_data = ldap_info; #.FN_PARS ServerSaslCreds VAL_PTR = ¶meter_tvb #.FN_BODY ServerSaslCreds tvbuff_t *parameter_tvb; ldap_conv_info_t *ldap_info; %(DEFAULT_BODY)s if (!parameter_tvb) return offset; ldap_info = pinfo->private_data; switch (ldap_info->auth_type) { /* For Kerberos V4, dissect it as a ticket. */ /* XXX - what about LDAP_AUTH_SIMPLE? */ case LDAP_AUTH_SASL: /* * All frames after this are assumed to use a security layer. * * XXX - won't work if there's another reply, with the security * layer, starting in the same TCP segment that ends this * reply, but as LDAP is a request/response protocol, and * as the client probably can't start using authentication until * it gets the bind reply and the server won't send a reply until * it gets a request, that probably won't happen. * * XXX - that assumption is invalid; it's not clear where the * hell you find out whether there's any security layer. In * one capture, we have two GSS-SPNEGO negotiations, both of * which select MS KRB5, and the only differences in the tokens * is in the RC4-HMAC ciphertext. The various * draft-ietf--cat-sasl-gssapi-NN.txt drafts seem to imply * that the RFC 2222 spoo with the bitmask and maximum * output message size stuff is done - but where does that * stuff show up? Is it in the ciphertext, which means it's * presumably encrypted? * * Grrr. We have to do a gross heuristic, checking whether the * putative LDAP message begins with 0x00 or not, making the * assumption that we won't have more than 2^24 bytes of * encapsulated stuff. */ ldap_info->first_auth_frame = pinfo->fd->num + 1; if (ldap_info->auth_mech != NULL && strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) { /* * This is a GSS-API token. */ call_dissector(gssapi_handle, parameter_tvb, pinfo, tree); } else if (ldap_info->auth_mech != NULL && strcmp(ldap_info->auth_mech, "GSSAPI") == 0) { /* * This is a GSS-API token. */ call_dissector(gssapi_handle, parameter_tvb, pinfo, tree); } break; } pinfo->private_data = ldap_info; #.FN_PARS LDAPString VAL_PTR = ¶meter_tvb #.FN_BODY LDAPString tvbuff_t *parameter_tvb = NULL; char *ldapstring; gchar *sc = NULL; /* semi-colon pointer */ %(DEFAULT_BODY)s if (parameter_tvb || (hf_index == hf_ldap_baseObject)) { ldap_do_protocolop(pinfo); if(parameter_tvb) ldapstring = tvb_get_ephemeral_string(parameter_tvb, 0, tvb_length_remaining(parameter_tvb, 0)); else ldapstring = ""; if(hf_index == hf_ldap_baseObject) { /* this is search - but it on the scanline */ if(check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "\"%%s\" ", ldapstring); if(ldm_tree) proto_item_append_text(ldm_tree, " \"%%s\"", ldapstring); } else if ((hf_index == hf_ldap_errorMessage) && result) { /* only show message if not success */ if(check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "(%%s) ", ldapstring); if(ldm_tree) proto_item_append_text(ldm_tree, " (%%s)", ldapstring); } else if (hf_index == hf_ldap_objectName) { if(check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "\"%%s\" ", ldapstring); if(ldm_tree) proto_item_append_text(ldm_tree, " \"%%s\"", ldapstring); } else if (hf_index == hf_ldap_attributeDesc){ /* remember the attribute description */ attributedesc_string=ldapstring; } else if (hf_index == hf_ldap_present){ /* remember the present name */ Filter_string=ldapstring; } else if (hf_index == hf_ldap_type) { /* remember attribute type name */ attr_type = ep_strdup(ldapstring); /* append it to the parent entry */ proto_item_append_text(tree, " %%s", attr_type); /* remove the ";binary" component if present */ if((sc = strchr(attr_type, ';')) != NULL) { if(!strcmp(sc, ";binary")) { *sc = '\0'; /* terminate the string */ is_binary_attr_type = TRUE; } } else { is_binary_attr_type = FALSE; } } } #.FN_PARS T_scope VAL_PTR = &scope #.FN_BODY T_scope gint scope; const gchar *valstr; %(DEFAULT_BODY)s ldap_do_protocolop(pinfo); valstr = val_to_str(scope, ldap_T_scope_vals, "Unknown scope(%%u)"); if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "%%s ", valstr); if(ldm_tree) proto_item_append_text(ldm_tree, " %%s", valstr); #.FN_PARS T_resultCode VAL_PTR = &result #.FN_BODY T_resultCode const gchar *valstr; %(DEFAULT_BODY)s ldap_do_protocolop(pinfo); if(result) { valstr = val_to_str(result, ldap_T_resultCode_vals, "Unknown result(%%u)"); if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "%%s ", valstr); if(ldm_tree) proto_item_append_text(ldm_tree, " %%s", valstr); } #.FN_PARS BindResponse_resultCode VAL_PTR = &result #.FN_BODY BindResponse_resultCode const gchar *valstr; %(DEFAULT_BODY)s ldap_do_protocolop(pinfo); if(result) { valstr = val_to_str(result, ldap_BindResponse_resultCode_vals, "Unknown result(%%u)"); if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "%%s ", valstr); if(ldm_tree) proto_item_append_text(ldm_tree, " %%s", valstr); } #.FN_BODY AttributeValue tvbuff_t *next_tvb; gchar *string; guint32 i, len; proto_item *pi; int old_offset = offset; /* extract the value of the octetstring */ offset = dissect_ber_octet_string(FALSE, pinfo, NULL, tvb, offset, hf_index, &next_tvb); /* if we have an attribute type that isn't binary see if there is a better dissector */ if(!attr_type || !dissector_try_string(ldap_name_dissector_table, attr_type, next_tvb, pinfo, tree)) { offset = old_offset; /* do the default thing */ %(DEFAULT_BODY)s } len = tvb_length_remaining(next_tvb, 0); for(i = 0; i < len; i++) if(!g_ascii_isprint(tvb_get_guint8(next_tvb, i))) break; if(i == len) { string = tvb_get_string(next_tvb, 0, tvb_length_remaining(next_tvb, 0)); pi = get_ber_last_created_item(); proto_item_set_text(pi, string); } #.FN_PARS AuthenticationChoice VAL_PTR = &branch #.FN_BODY AuthenticationChoice gint branch = -1; gint auth = -1; const gchar *valstr; %(DEFAULT_BODY)s ldap_do_protocolop(pinfo); if((branch > -1) && (branch < (gint)(sizeof AuthenticationChoice_choice/sizeof AuthenticationChoice_choice[0]))) auth = AuthenticationChoice_choice[branch].value; valstr = val_to_str(auth, ldap_AuthenticationChoice_vals, "Unknown auth(%%u)"); if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, "%%s ", valstr); if(ldm_tree) proto_item_append_text(ldm_tree, " %%s", valstr); #.FN_BODY UnbindRequest implicit_tag = TRUE; /* correct problem with asn2wrs */ %(DEFAULT_BODY)s ldap_do_protocolop(pinfo); #.FN_HDR SearchRequest/filter Filter_string=NULL; #.FN_FTR SearchRequest/filter Filter_string=NULL; and_filter_string=NULL; #.FN_FTR Filter/equalityMatch Filter_string=ep_strdup_printf("(%s=%s)",attributedesc_string,assertionvalue_string); #.FN_FTR Filter/greaterOrEqual Filter_string=ep_strdup_printf("(%s>=%s)",attributedesc_string,assertionvalue_string); #.FN_FTR Filter/lessOrEqual Filter_string=ep_strdup_printf("(%s<=%s)",attributedesc_string,assertionvalue_string); #.FN_FTR Filter/approxMatch Filter_string=ep_strdup_printf("(%s~=%s)",attributedesc_string,assertionvalue_string); #.FN_BODY Filter/and/_item offset=dissect_ldap_Filter(FALSE, tvb, offset, pinfo, tree, hf_ldap_and_item); if(and_filter_string){ and_filter_string=ep_strdup_printf("(&%%s%%s)",and_filter_string,Filter_string); } else { and_filter_string=Filter_string; } #.FN_BODY Filter/and const ber_sequence_t and_set_of[1] = { { BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_and_item }, }; proto_tree *tr=NULL; proto_item *it=NULL; char *old_and_filter_string=and_filter_string; and_filter_string=NULL; if(tree){ it=proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "and: "); tr=proto_item_add_subtree(it, ett_ldap_T_and); } offset = dissect_ber_set_of(implicit_tag, pinfo, tr, tvb, offset, and_set_of, -1, ett_ldap_T_and); proto_item_append_text(it, " %%s", and_filter_string); Filter_string=ep_strdup_printf("%%s",and_filter_string); and_filter_string=old_and_filter_string; #.FN_BODY Filter/or/_item offset=dissect_ldap_Filter(FALSE, tvb, offset, pinfo, tree, hf_ldap_or_item); if(and_filter_string){ and_filter_string=ep_strdup_printf("(|%%s%%s)",and_filter_string,Filter_string); } else { and_filter_string=Filter_string; } #.FN_BODY Filter/or const ber_sequence_t or_set_of[1] = { { BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_or_item }, }; proto_tree *tr=NULL; proto_item *it=NULL; char *old_and_filter_string=and_filter_string; and_filter_string=NULL; if(tree){ it=proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "or: "); tr=proto_item_add_subtree(it, ett_ldap_T_or); } offset = dissect_ber_set_of(implicit_tag, pinfo, tr, tvb, offset, or_set_of, -1, ett_ldap_T_or); proto_item_append_text(it, " %%s", and_filter_string); Filter_string=ep_strdup_printf("%%s",and_filter_string); and_filter_string=old_and_filter_string; #.FN_FTR Filter/present Filter_string=ep_strdup_printf("(%s=*)",Filter_string); #.FN_FTR Filter/not Filter_string=ep_strdup_printf("(!%s)",Filter_string); #.FN_FTR Filter/extensibleMatch Filter_string=""; #.FN_FTR Filter/substrings Filter_string=""; #.FN_BODY Filter proto_tree *tr=NULL; proto_item *it=NULL; if(tree){ it=proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "Filter: "); tr=proto_item_add_subtree(it, ett_ldap_Filter); } offset = dissect_ber_choice(pinfo, tr, tvb, offset, Filter_choice, -1, ett_ldap_Filter, NULL); proto_item_append_text(it, "%%s", Filter_string); #.NO_EMIT AttributeType Attribute AssertionValue