@@ -349,15 +349,14 @@ void ntlm_internal_set_version(uint8_t major, uint8_t minor,
349
349
350
350
static int ntlm_encode_version (struct ntlm_ctx * ctx ,
351
351
struct ntlm_buffer * buffer ,
352
- size_t * data_offs )
352
+ size_t data_offs )
353
353
{
354
- if (* data_offs + sizeof (struct wire_version ) > buffer -> length ) {
354
+ if (data_offs + sizeof (struct wire_version ) > buffer -> length ) {
355
355
return ERR_ENCODE ;
356
356
}
357
357
358
- memcpy (& buffer -> data [* data_offs ], & ntlmssp_version ,
358
+ memcpy (& buffer -> data [data_offs ], & ntlmssp_version ,
359
359
sizeof (struct wire_version ));
360
- * data_offs += sizeof (struct wire_version );
361
360
return 0 ;
362
361
}
363
362
@@ -932,6 +931,12 @@ int ntlm_encode_neg_msg(struct ntlm_ctx *ctx, uint32_t flags,
932
931
if (ret ) goto done ;
933
932
}
934
933
934
+ if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
935
+ ret = ntlm_encode_version (ctx , & buffer ,
936
+ (char * )& msg -> version - (char * )msg );
937
+ if (ret ) goto done ;
938
+ }
939
+
935
940
done :
936
941
if (ret ) {
937
942
safefree (buffer .data );
@@ -959,6 +964,14 @@ int ntlm_decode_neg_msg(struct ntlm_ctx *ctx,
959
964
960
965
neg_flags = le32toh (msg -> neg_flags );
961
966
967
+ if ((neg_flags & NTLMSSP_NEGOTIATE_VERSION ) == 0 ) {
968
+ /* adjust the payload offset to point to the
969
+ * version field, for compatibility with older
970
+ * clients that completely omitted the structure
971
+ * on the wire */
972
+ payload_offs -= sizeof (struct wire_version );
973
+ }
974
+
962
975
if (domain &&
963
976
(neg_flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED )) {
964
977
ret = ntlm_decode_oem_str (& msg -> domain_name , buffer ,
@@ -1003,10 +1016,6 @@ int ntlm_encode_chal_msg(struct ntlm_ctx *ctx,
1003
1016
1004
1017
buffer .length = sizeof (struct wire_chal_msg );
1005
1018
1006
- if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
1007
- buffer .length += sizeof (struct wire_version );
1008
- }
1009
-
1010
1019
if ((flags & NTLMSSP_TARGET_TYPE_SERVER )
1011
1020
|| (flags & NTLMSSP_TARGET_TYPE_DOMAIN )) {
1012
1021
if (!target_name ) return EINVAL ;
@@ -1035,7 +1044,8 @@ int ntlm_encode_chal_msg(struct ntlm_ctx *ctx,
1035
1044
1036
1045
/* this must be first as it pushes the payload further down */
1037
1046
if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
1038
- ret = ntlm_encode_version (ctx , & buffer , & data_offs );
1047
+ ret = ntlm_encode_version (ctx , & buffer ,
1048
+ (char * )& msg -> version - (char * )msg );
1039
1049
if (ret ) goto done ;
1040
1050
}
1041
1051
@@ -1077,6 +1087,7 @@ int ntlm_decode_chal_msg(struct ntlm_ctx *ctx,
1077
1087
{
1078
1088
struct wire_chal_msg * msg ;
1079
1089
size_t payload_offs ;
1090
+ size_t base_chal_size ;
1080
1091
uint32_t flags ;
1081
1092
char * trg = NULL ;
1082
1093
int ret = 0 ;
@@ -1089,6 +1100,16 @@ int ntlm_decode_chal_msg(struct ntlm_ctx *ctx,
1089
1100
payload_offs = (char * )msg -> payload - (char * )msg ;
1090
1101
1091
1102
flags = le32toh (msg -> neg_flags );
1103
+ base_chal_size = sizeof (struct wire_chal_msg );
1104
+
1105
+ if ((flags & NTLMSSP_NEGOTIATE_VERSION ) == 0 ) {
1106
+ /* adjust the payload offset to point to the
1107
+ * version field, for compatibility with older
1108
+ * clients that completely omitted the structure
1109
+ * on the wire */
1110
+ payload_offs -= sizeof (struct wire_version );
1111
+ base_chal_size -= sizeof (struct wire_version );
1112
+ }
1092
1113
1093
1114
if ((flags & NTLMSSP_TARGET_TYPE_SERVER )
1094
1115
|| (flags & NTLMSSP_TARGET_TYPE_DOMAIN )) {
@@ -1107,7 +1128,7 @@ int ntlm_decode_chal_msg(struct ntlm_ctx *ctx,
1107
1128
1108
1129
/* if we allowed a broken short challenge message from an old
1109
1130
* server we must stop here */
1110
- if (buffer -> length < sizeof ( struct wire_chal_msg ) ) {
1131
+ if (buffer -> length < base_chal_size ) {
1111
1132
if (flags & NTLMSSP_NEGOTIATE_TARGET_INFO ) {
1112
1133
ret = ERR_DECODE ;
1113
1134
}
@@ -1190,9 +1211,6 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
1190
1211
if (enc_sess_key ) {
1191
1212
buffer .length += enc_sess_key -> length ;
1192
1213
}
1193
- if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
1194
- buffer .length += sizeof (struct wire_version );
1195
- }
1196
1214
if (mic ) {
1197
1215
buffer .length += 16 ;
1198
1216
}
@@ -1207,11 +1225,12 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
1207
1225
1208
1226
/* this must be first as it pushes the payload further down */
1209
1227
if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
1210
- ret = ntlm_encode_version (ctx , & buffer , & data_offs );
1228
+ ret = ntlm_encode_version (ctx , & buffer ,
1229
+ (char * )& msg -> version - (char * )msg );
1211
1230
if (ret ) goto done ;
1212
1231
}
1213
1232
1214
- /* this must be second as it pushes the payload further down */
1233
+ /* this pushes the payload further down */
1215
1234
if (mic ) {
1216
1235
memset (& buffer .data [data_offs ], 0 , mic -> length );
1217
1236
/* return the actual pointer back in the mic, as it will
@@ -1293,6 +1312,7 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
1293
1312
struct ntlm_buffer * mic )
1294
1313
{
1295
1314
struct wire_auth_msg * msg ;
1315
+ uint32_t neg_flags ;
1296
1316
size_t payload_offs ;
1297
1317
char * dom = NULL ;
1298
1318
char * usr = NULL ;
@@ -1308,23 +1328,38 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
1308
1328
msg = (struct wire_auth_msg * )buffer -> data ;
1309
1329
payload_offs = (char * )msg -> payload - (char * )msg ;
1310
1330
1311
- /* this must be first as it pushes the payload further down */
1312
- if (flags & NTLMSSP_NEGOTIATE_VERSION ) {
1313
- /* skip version for now */
1314
- payload_offs += sizeof (struct wire_version );
1331
+ neg_flags = le32toh (msg -> neg_flags );
1332
+ if ((neg_flags & NTLMSSP_NEGOTIATE_VERSION ) == 0 ) {
1333
+ /* adjust the payload offset to point to the
1334
+ * version field, for compatibility with older
1335
+ * clients that completely omitted the structure
1336
+ * on the wire */
1337
+ payload_offs -= sizeof (struct wire_version );
1315
1338
}
1316
1339
1317
1340
/* Unconditionally copy 16 bytes for the MIC, if it was really
1318
1341
* added by the client it will be flagged in the AV_PAIR contained
1319
1342
* in the NT Response, that will be fully decoded later by the caller
1320
1343
* and the MIC checked otherwise these 16 bytes will just be ignored */
1321
1344
if (mic ) {
1345
+ size_t mic_offs = payload_offs ;
1346
+
1322
1347
if (mic -> length < 16 ) return ERR_DECODE ;
1323
- /* mic is at payload_offs right now */
1324
- if (buffer -> length - payload_offs < 16 ) return ERR_DECODE ;
1325
- memcpy (mic -> data , & buffer -> data [payload_offs ], 16 );
1326
- /* NOTE: we do not push down the payload because we do not know that
1327
- * the MIC is actually present yet for real */
1348
+
1349
+ if ((neg_flags & NTLMSSP_NEGOTIATE_VERSION ) == 0 ) {
1350
+ struct wire_version zver = {0 };
1351
+ /* mic is at payload_offs right now, but this offset may be
1352
+ * wrongly reduced for compatibility with older clients,
1353
+ * if all bytes are zeroed, then it means there was an actual
1354
+ * empty version struct */
1355
+ if (memcmp (& msg -> version , & zver ,
1356
+ sizeof (struct wire_version )) == 0 ) {
1357
+ mic_offs += sizeof (struct wire_version );
1358
+ }
1359
+ }
1360
+
1361
+ if (buffer -> length - mic_offs < 16 ) return ERR_DECODE ;
1362
+ memcpy (mic -> data , & buffer -> data [mic_offs ], 16 );
1328
1363
}
1329
1364
1330
1365
if (msg -> lm_chalresp .len != 0 && lm_chalresp ) {
0 commit comments