Skip to content

Commit 110b589

Browse files
authored
Merge pull request libgit2#5052 from libgit2/ethomson/netrefactor
Add NTLM support for HTTP(s) servers and proxies
2 parents f4584a1 + 7ea8630 commit 110b589

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5957
-914
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
6767
OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF)
6868
SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
6969

70+
IF (UNIX)
71+
OPTION(USE_NTLMCLIENT "Enable NTLM support on Unix." ON )
72+
ENDIF()
73+
7074
IF (UNIX AND NOT APPLE)
7175
OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF)
7276
ENDIF()

ci/test.ps1

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,25 @@ Write-Host "## Configuring test environment"
3838
Write-Host "##############################################################################"
3939

4040
if (-not $Env:SKIP_PROXY_TESTS) {
41+
Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.7.0/poxyproxy-0.7.0.jar -OutFile poxyproxy.jar
42+
43+
Write-Host ""
44+
Write-Host "Starting HTTP proxy (Basic)..."
45+
javaw -jar poxyproxy.jar --port 8080 --credentials foo:bar --auth-type basic --quiet
46+
4147
Write-Host ""
42-
Write-Host "Starting HTTP proxy..."
43-
Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.4.0/poxyproxy-0.4.0.jar -OutFile poxyproxy.jar
44-
javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar --quiet
48+
Write-Host "Starting HTTP proxy (NTLM)..."
49+
javaw -jar poxyproxy.jar --port 8090 --credentials foo:bar --auth-type ntlm --quiet
4550
}
4651

47-
Write-Host ""
48-
Write-Host "##############################################################################"
49-
Write-Host "## Running (offline) tests"
50-
Write-Host "##############################################################################"
52+
if (-not $Env:SKIP_OFFLINE_TESTS) {
53+
Write-Host ""
54+
Write-Host "##############################################################################"
55+
Write-Host "## Running (offline) tests"
56+
Write-Host "##############################################################################"
5157

52-
run_test offline
58+
run_test offline
59+
}
5360

5461
if ($Env:RUN_INVASIVE_TESTS) {
5562
Write-Host ""
@@ -76,14 +83,24 @@ if (-not $Env:SKIP_ONLINE_TESTS) {
7683
}
7784

7885
if (-not $Env:SKIP_PROXY_TESTS) {
86+
# Test HTTP Basic authentication
7987
Write-Host ""
80-
Write-Host "Running proxy tests"
88+
Write-Host "Running proxy tests (Basic authentication)"
8189
Write-Host ""
8290

8391
$Env:GITTEST_REMOTE_PROXY_HOST="localhost:8080"
8492
$Env:GITTEST_REMOTE_PROXY_USER="foo"
8593
$Env:GITTEST_REMOTE_PROXY_PASS="bar"
94+
run_test proxy
8695

96+
# Test NTLM authentication
97+
Write-Host ""
98+
Write-Host "Running proxy tests (NTLM authentication)"
99+
Write-Host ""
100+
101+
$Env:GITTEST_REMOTE_PROXY_HOST="localhost:8090"
102+
$Env:GITTEST_REMOTE_PROXY_USER="foo"
103+
$Env:GITTEST_REMOTE_PROXY_PASS="bar"
87104
run_test proxy
88105

89106
$Env:GITTEST_REMOTE_PROXY_HOST=$null

ci/test.sh

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,15 @@ if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
7878
fi
7979

8080
if [ -z "$SKIP_PROXY_TESTS" ]; then
81-
echo "Starting HTTP proxy..."
82-
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.4.0/poxyproxy-0.4.0.jar >poxyproxy.jar
83-
java -jar poxyproxy.jar -d --address 127.0.0.1 --port 8080 --credentials foo:bar --quiet &
81+
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.7.0/poxyproxy-0.7.0.jar >poxyproxy.jar
82+
83+
echo ""
84+
echo "Starting HTTP proxy (Basic)..."
85+
java -jar poxyproxy.jar --address 127.0.0.1 --port 8080 --credentials foo:bar --auth-type basic --quiet &
86+
87+
echo ""
88+
echo "Starting HTTP proxy (NTLM)..."
89+
java -jar poxyproxy.jar --address 127.0.0.1 --port 8090 --credentials foo:bar --auth-type ntlm --quiet &
8490
fi
8591

8692
if [ -z "$SKIP_SSH_TESTS" ]; then
@@ -175,7 +181,7 @@ fi
175181

176182
if [ -z "$SKIP_PROXY_TESTS" ]; then
177183
echo ""
178-
echo "Running proxy tests"
184+
echo "Running proxy tests (Basic authentication)"
179185
echo ""
180186

181187
export GITTEST_REMOTE_PROXY_HOST="localhost:8080"
@@ -185,6 +191,18 @@ if [ -z "$SKIP_PROXY_TESTS" ]; then
185191
unset GITTEST_REMOTE_PROXY_HOST
186192
unset GITTEST_REMOTE_PROXY_USER
187193
unset GITTEST_REMOTE_PROXY_PASS
194+
195+
echo ""
196+
echo "Running proxy tests (NTLM authentication)"
197+
echo ""
198+
199+
export GITTEST_REMOTE_PROXY_HOST="localhost:8090"
200+
export GITTEST_REMOTE_PROXY_USER="foo"
201+
export GITTEST_REMOTE_PROXY_PASS="bar"
202+
run_test proxy
203+
unset GITTEST_REMOTE_PROXY_HOST
204+
unset GITTEST_REMOTE_PROXY_USER
205+
unset GITTEST_REMOTE_PROXY_PASS
188206
fi
189207

190208
if [ -z "$SKIP_SSH_TESTS" ]; then

deps/ntlmclient/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "unicode_builtin.c" "util.c")
2+
3+
ADD_DEFINITIONS(-DNTLM_STATIC=1)
4+
5+
IF (HTTPS_BACKEND STREQUAL "SecureTransport")
6+
ADD_DEFINITIONS(-DCRYPT_COMMONCRYPTO)
7+
SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c")
8+
ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
9+
ADD_DEFINITIONS(-DCRYPT_OPENSSL)
10+
SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c")
11+
ELSEIF (HTTPS_BACKEND STREQUAL "mbedTLS")
12+
ADD_DEFINITIONS(-DCRYPT_MBEDTLS)
13+
SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c")
14+
ELSE ()
15+
MESSAGE(FATAL_ERROR "Unable to use libgit2's HTTPS backend (${HTTPS_BACKEND}) for NTLM crypto")
16+
ENDIF()
17+
18+
ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_CRYPTO})

deps/ntlmclient/compat.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) Edward Thomson. All rights reserved.
3+
*
4+
* This file is part of ntlmclient, distributed under the MIT license.
5+
* For full terms and copyright information, and for third-party
6+
* copyright information, see the included LICENSE.txt file.
7+
*/
8+
9+
#ifndef PRIVATE_COMPAT_H__
10+
#define PRIVATE_COMPAT_H__
11+
12+
#if defined (_MSC_VER)
13+
typedef unsigned char bool;
14+
# ifndef true
15+
# define true 1
16+
# endif
17+
# ifndef false
18+
# define false 0
19+
# endif
20+
#else
21+
# include <stdbool.h>
22+
#endif
23+
24+
#ifdef __linux__
25+
# include <endian.h>
26+
# define htonll htobe64
27+
#endif
28+
29+
#ifndef MIN
30+
# define MIN(x, y) (((x) < (y)) ? (x) : (y))
31+
#endif
32+
33+
#endif /* PRIVATE_COMPAT_H__ */

deps/ntlmclient/crypt.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) Edward Thomson. All rights reserved.
3+
*
4+
* This file is part of ntlmclient, distributed under the MIT license.
5+
* For full terms and copyright information, and for third-party
6+
* copyright information, see the included LICENSE.txt file.
7+
*/
8+
9+
#ifndef PRIVATE_CRYPT_COMMON_H__
10+
#define PRIVATE_CRYPT_COMMON_H__
11+
12+
#if defined(CRYPT_OPENSSL)
13+
# include "crypt_openssl.h"
14+
#elif defined(CRYPT_MBEDTLS)
15+
# include "crypt_mbedtls.h"
16+
#elif defined(CRYPT_COMMONCRYPTO)
17+
# include "crypt_commoncrypto.h"
18+
#else
19+
# error "no crypto support"
20+
#endif
21+
22+
#define CRYPT_DES_BLOCKSIZE 8
23+
#define CRYPT_MD4_DIGESTSIZE 16
24+
#define CRYPT_MD5_DIGESTSIZE 16
25+
26+
typedef unsigned char ntlm_des_block[CRYPT_DES_BLOCKSIZE];
27+
28+
extern bool ntlm_random_bytes(
29+
ntlm_client *ntlm,
30+
unsigned char *out,
31+
size_t len);
32+
33+
extern bool ntlm_des_encrypt(
34+
ntlm_des_block *out,
35+
ntlm_des_block *plaintext,
36+
ntlm_des_block *key);
37+
38+
extern bool ntlm_md4_digest(
39+
unsigned char out[CRYPT_MD4_DIGESTSIZE],
40+
const unsigned char *in,
41+
size_t in_len);
42+
43+
extern ntlm_hmac_ctx *ntlm_hmac_ctx_init(void);
44+
45+
extern bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx);
46+
47+
extern bool ntlm_hmac_md5_init(
48+
ntlm_hmac_ctx *ctx,
49+
const unsigned char *key,
50+
size_t key_len);
51+
52+
extern bool ntlm_hmac_md5_update(
53+
ntlm_hmac_ctx *ctx,
54+
const unsigned char *data,
55+
size_t data_len);
56+
57+
extern bool ntlm_hmac_md5_final(
58+
unsigned char *out,
59+
size_t *out_len,
60+
ntlm_hmac_ctx *ctx);
61+
62+
extern void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx);
63+
64+
#endif /* PRIVATE_CRYPT_COMMON_H__ */
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright (c) Edward Thomson. All rights reserved.
3+
*
4+
* This file is part of ntlmclient, distributed under the MIT license.
5+
* For full terms and copyright information, and for third-party
6+
* copyright information, see the included LICENSE.txt file.
7+
*/
8+
9+
#include <stdlib.h>
10+
#include <stdint.h>
11+
#include <string.h>
12+
#include <fcntl.h>
13+
#include <unistd.h>
14+
#include <errno.h>
15+
16+
#include <CommonCrypto/CommonCrypto.h>
17+
18+
#include "ntlm.h"
19+
#include "crypt.h"
20+
21+
bool ntlm_random_bytes(
22+
ntlm_client *ntlm,
23+
unsigned char *out,
24+
size_t len)
25+
{
26+
int fd, ret;
27+
size_t total = 0;
28+
29+
if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
30+
ntlm_client_set_errmsg(ntlm, strerror(errno));
31+
return false;
32+
}
33+
34+
while (total < len) {
35+
if ((ret = read(fd, out, (len - total))) < 0) {
36+
ntlm_client_set_errmsg(ntlm, strerror(errno));
37+
return false;
38+
} else if (ret == 0) {
39+
ntlm_client_set_errmsg(ntlm, "unexpected eof on random device");
40+
return false;
41+
}
42+
43+
total += ret;
44+
}
45+
46+
close(fd);
47+
return true;
48+
}
49+
50+
bool ntlm_des_encrypt(
51+
ntlm_des_block *out,
52+
ntlm_des_block *plaintext,
53+
ntlm_des_block *key)
54+
{
55+
size_t written;
56+
57+
CCCryptorStatus result = CCCrypt(kCCEncrypt,
58+
kCCAlgorithmDES, kCCOptionECBMode,
59+
key, sizeof(ntlm_des_block), NULL,
60+
plaintext, sizeof(ntlm_des_block),
61+
out, sizeof(ntlm_des_block), &written);
62+
63+
return (result == kCCSuccess) ? true : false;
64+
}
65+
66+
bool ntlm_md4_digest(
67+
unsigned char out[CRYPT_MD4_DIGESTSIZE],
68+
const unsigned char *in,
69+
size_t in_len)
70+
{
71+
return !!CC_MD4(in, in_len, out);
72+
}
73+
74+
ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
75+
{
76+
return calloc(1, sizeof(ntlm_hmac_ctx));
77+
}
78+
79+
bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
80+
{
81+
memset(ctx, 0, sizeof(ntlm_hmac_ctx));
82+
return true;
83+
}
84+
85+
bool ntlm_hmac_md5_init(
86+
ntlm_hmac_ctx *ctx,
87+
const unsigned char *key,
88+
size_t key_len)
89+
{
90+
CCHmacInit(&ctx->native, kCCHmacAlgMD5, key, key_len);
91+
return true;
92+
}
93+
94+
bool ntlm_hmac_md5_update(
95+
ntlm_hmac_ctx *ctx,
96+
const unsigned char *data,
97+
size_t data_len)
98+
{
99+
CCHmacUpdate(&ctx->native, data, data_len);
100+
return true;
101+
}
102+
103+
bool ntlm_hmac_md5_final(
104+
unsigned char *out,
105+
size_t *out_len,
106+
ntlm_hmac_ctx *ctx)
107+
{
108+
if (*out_len < CRYPT_MD5_DIGESTSIZE)
109+
return false;
110+
111+
CCHmacFinal(&ctx->native, out);
112+
113+
*out_len = CRYPT_MD5_DIGESTSIZE;
114+
return true;
115+
}
116+
117+
void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
118+
{
119+
free(ctx);
120+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) Edward Thomson. All rights reserved.
3+
*
4+
* This file is part of ntlmclient, distributed under the MIT license.
5+
* For full terms and copyright information, and for third-party
6+
* copyright information, see the included LICENSE.txt file.
7+
*/
8+
9+
#ifndef PRIVATE_CRYPT_COMMONCRYPTO_H__
10+
#define PRIVATE_CRYPT_COMMONCRYPTO_H__
11+
12+
#include <CommonCrypto/CommonCrypto.h>
13+
14+
typedef struct {
15+
CCHmacContext native;
16+
} ntlm_hmac_ctx;
17+
18+
#endif /* PRIVATE_CRYPT_COMMONCRYPTO_H__ */

0 commit comments

Comments
 (0)