1/* 2 Unix SMB/CIFS implementation. 3 4 routines for marshalling/unmarshalling special ntlmssp structures 5 6 Copyright (C) Guenther Deschner 2009 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "../librpc/gen_ndr/ndr_ntlmssp.h" 24 25_PUBLIC_ size_t ndr_ntlmssp_string_length(uint32_t negotiate_flags, const char *s) 26{ 27 if (!s) { 28 return 0; 29 } 30 31 if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE) { 32 return strlen(s) * 2; 33 } 34 35 return strlen(s); 36} 37 38_PUBLIC_ uint32_t ndr_ntlmssp_negotiated_string_flags(uint32_t negotiate_flags) 39{ 40 uint32_t flags = LIBNDR_FLAG_STR_NOTERM | 41 LIBNDR_FLAG_STR_CHARLEN | 42 LIBNDR_FLAG_REMAINING; 43 44 if (!(negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)) { 45 flags |= LIBNDR_FLAG_STR_ASCII; 46 } 47 48 return flags; 49} 50 51_PUBLIC_ enum ndr_err_code ndr_push_AV_PAIR_LIST(struct ndr_push *ndr, int ndr_flags, const struct AV_PAIR_LIST *r) 52{ 53 uint32_t cntr_pair_0; 54 if (ndr_flags & NDR_SCALARS) { 55 NDR_CHECK(ndr_push_align(ndr, 4)); 56 for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) { 57 NDR_CHECK(ndr_push_AV_PAIR(ndr, NDR_SCALARS, &r->pair[cntr_pair_0])); 58 } 59 } 60 if (ndr_flags & NDR_BUFFERS) { 61 for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) { 62 NDR_CHECK(ndr_push_AV_PAIR(ndr, NDR_BUFFERS, &r->pair[cntr_pair_0])); 63 } 64 } 65 return NDR_ERR_SUCCESS; 66} 67 68_PUBLIC_ enum ndr_err_code ndr_pull_AV_PAIR_LIST(struct ndr_pull *ndr, int ndr_flags, struct AV_PAIR_LIST *r) 69{ 70 uint32_t cntr_pair_0; 71 TALLOC_CTX *_mem_save_pair_0; 72 if (ndr_flags & NDR_SCALARS) { 73 uint32_t offset = 0; 74 NDR_CHECK(ndr_pull_align(ndr, 4)); 75 r->count = 0; 76 if (ndr->data_size > 0) { 77 NDR_PULL_NEED_BYTES(ndr, 4); 78 } 79 while (offset + 4 <= ndr->data_size) { 80 uint16_t length; 81 uint16_t type; 82 type = SVAL(ndr->data + offset, 0); 83 if (type == MsvAvEOL) { 84 r->count++; 85 break; 86 } 87 length = SVAL(ndr->data + offset, 2); 88 offset += length + 4; 89 r->count++; 90 } 91 NDR_PULL_ALLOC_N(ndr, r->pair, r->count); 92 _mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr); 93 NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0); 94 for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) { 95 NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_SCALARS, &r->pair[cntr_pair_0])); 96 } 97 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0); 98 } 99 if (ndr_flags & NDR_BUFFERS) { 100 _mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr); 101 NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0); 102 for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) { 103 NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_BUFFERS, &r->pair[cntr_pair_0])); 104 } 105 NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0); 106 } 107 return NDR_ERR_SUCCESS; 108} 109 110_PUBLIC_ void ndr_print_ntlmssp_nt_response(TALLOC_CTX *mem_ctx, 111 struct smb_iconv_convenience *ic, 112 const DATA_BLOB *nt_response, 113 bool ntlmv2) 114{ 115 enum ndr_err_code ndr_err; 116 117 if (ntlmv2) { 118 struct NTLMv2_RESPONSE nt; 119 if (nt_response->length > 24) { 120 ndr_err = ndr_pull_struct_blob(nt_response, mem_ctx, ic, &nt, 121 (ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE); 122 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 123 NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &nt); 124 } 125 } 126 } else { 127 struct NTLM_RESPONSE nt; 128 if (nt_response->length == 24) { 129 ndr_err = ndr_pull_struct_blob(nt_response, mem_ctx, ic, &nt, 130 (ndr_pull_flags_fn_t)ndr_pull_NTLM_RESPONSE); 131 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 132 NDR_PRINT_DEBUG(NTLM_RESPONSE, &nt); 133 } 134 } 135 } 136} 137 138_PUBLIC_ void ndr_print_ntlmssp_lm_response(TALLOC_CTX *mem_ctx, 139 struct smb_iconv_convenience *ic, 140 const DATA_BLOB *lm_response, 141 bool ntlmv2) 142{ 143 enum ndr_err_code ndr_err; 144 145 if (ntlmv2) { 146 struct LMv2_RESPONSE lm; 147 if (lm_response->length == 24) { 148 ndr_err = ndr_pull_struct_blob(lm_response, mem_ctx, ic, &lm, 149 (ndr_pull_flags_fn_t)ndr_pull_LMv2_RESPONSE); 150 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 151 NDR_PRINT_DEBUG(LMv2_RESPONSE, &lm); 152 } 153 } 154 } else { 155 struct LM_RESPONSE lm; 156 if (lm_response->length == 24) { 157 ndr_err = ndr_pull_struct_blob(lm_response, mem_ctx, ic, &lm, 158 (ndr_pull_flags_fn_t)ndr_pull_LM_RESPONSE); 159 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 160 NDR_PRINT_DEBUG(LM_RESPONSE, &lm); 161 } 162 } 163 } 164} 165 166_PUBLIC_ void ndr_print_ntlmssp_Version(struct ndr_print *ndr, const char *name, const union ntlmssp_Version *r) 167{ 168 int level; 169 level = ndr_print_get_switch_value(ndr, r); 170 switch (level) { 171 case NTLMSSP_NEGOTIATE_VERSION: 172 ndr_print_VERSION(ndr, name, &r->version); 173 break; 174 175 default: 176 break; 177 178 } 179} 180 181 182