Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
df4dfaad
Commit
df4dfaad
authored
Jan 16, 2017
by
Carlos Martín Nieto
Committed by
GitHub
Jan 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4055 from ethomson/ethomson/ntlm
WinHTTP: support best auth mechanism
parents
cb76eed5
4e4a1460
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
60 additions
and
63 deletions
+60
-63
src/transports/winhttp.c
+60
-63
No files found.
src/transports/winhttp.c
View file @
df4dfaad
...
@@ -68,7 +68,8 @@ static const IID IID_IInternetSecurityManager_mingw =
...
@@ -68,7 +68,8 @@ static const IID IID_IInternetSecurityManager_mingw =
typedef
enum
{
typedef
enum
{
GIT_WINHTTP_AUTH_BASIC
=
1
,
GIT_WINHTTP_AUTH_BASIC
=
1
,
GIT_WINHTTP_AUTH_NEGOTIATE
=
2
,
GIT_WINHTTP_AUTH_NTLM
=
2
,
GIT_WINHTTP_AUTH_NEGOTIATE
=
4
,
}
winhttp_authmechanism_t
;
}
winhttp_authmechanism_t
;
typedef
struct
{
typedef
struct
{
...
@@ -95,79 +96,66 @@ typedef struct {
...
@@ -95,79 +96,66 @@ typedef struct {
git_cred
*
cred
;
git_cred
*
cred
;
git_cred
*
url_cred
;
git_cred
*
url_cred
;
git_cred
*
proxy_cred
;
git_cred
*
proxy_cred
;
int
auth_mechanism
;
int
auth_mechanism
s
;
HINTERNET
session
;
HINTERNET
session
;
HINTERNET
connection
;
HINTERNET
connection
;
}
winhttp_subtransport
;
}
winhttp_subtransport
;
static
int
apply_basic_credential_proxy
(
HINTERNET
request
,
git_cred
*
cred
)
static
int
_apply_userpass_credential
(
HINTERNET
request
,
DWORD
target
,
DWORD
scheme
,
git_cred
*
cred
)
{
{
git_cred_userpass_plaintext
*
c
=
(
git_cred_userpass_plaintext
*
)
cred
;
git_cred_userpass_plaintext
*
c
=
(
git_cred_userpass_plaintext
*
)
cred
;
wchar_t
*
user
,
*
pass
;
wchar_t
*
user
,
*
pass
;
int
error
;
int
user_len
=
0
,
pass_len
=
0
,
error
=
0
;
if
((
error
=
git__utf8_to_16_alloc
(
&
user
,
c
->
username
))
<
0
)
if
((
error
=
user_len
=
git__utf8_to_16_alloc
(
&
user
,
c
->
username
))
<
0
)
return
error
;
goto
done
;
if
((
error
=
git__utf8_to_16_alloc
(
&
pass
,
c
->
password
))
<
0
)
if
((
error
=
pass_len
=
git__utf8_to_16_alloc
(
&
pass
,
c
->
password
))
<
0
)
return
error
;
goto
done
;
if
(
!
WinHttpSetCredentials
(
request
,
WINHTTP_AUTH_TARGET_PROXY
,
WINHTTP_AUTH_SCHEME_BASIC
,
if
(
!
WinHttpSetCredentials
(
request
,
target
,
scheme
,
user
,
pass
,
NULL
))
{
user
,
pass
,
NULL
))
{
giterr_set
(
GITERR_OS
,
"failed to set credentials"
);
giterr_set
(
GITERR_OS
,
"failed to set proxy auth"
);
error
=
-
1
;
error
=
-
1
;
}
}
done:
if
(
user_len
>
0
)
git__memzero
(
user
,
user_len
*
sizeof
(
wchar_t
));
if
(
pass_len
>
0
)
git__memzero
(
pass
,
pass_len
*
sizeof
(
wchar_t
));
git__free
(
user
);
git__free
(
user
);
git__free
(
pass
);
git__free
(
pass
);
return
error
;
return
error
;
}
}
static
int
apply_
basic_credential
(
HINTERNET
request
,
git_cred
*
cred
)
static
int
apply_
userpass_credential_proxy
(
HINTERNET
request
,
git_cred
*
cred
)
{
{
git_cred_userpass_plaintext
*
c
=
(
git_cred_userpass_plaintext
*
)
cred
;
return
_apply_userpass_credential
(
request
,
WINHTTP_AUTH_TARGET_PROXY
,
git_buf
buf
=
GIT_BUF_INIT
,
raw
=
GIT_BUF_INIT
;
WINHTTP_AUTH_SCHEME_BASIC
,
cred
);
wchar_t
*
wide
=
NULL
;
}
int
error
=
-
1
,
wide_len
;
git_buf_printf
(
&
raw
,
"%s:%s"
,
c
->
username
,
c
->
password
);
if
(
git_buf_oom
(
&
raw
)
||
git_buf_puts
(
&
buf
,
"Authorization: Basic "
)
<
0
||
git_buf_encode_base64
(
&
buf
,
git_buf_cstr
(
&
raw
),
raw
.
size
)
<
0
)
goto
on_error
;
if
((
wide_len
=
git__utf8_to_16_alloc
(
&
wide
,
git_buf_cstr
(
&
buf
)))
<
0
)
{
static
int
apply_userpass_credential
(
HINTERNET
request
,
int
mechanisms
,
git_cred
*
cred
)
giterr_set
(
GITERR_OS
,
"failed to convert string to wide form"
);
{
goto
on_error
;
DWORD
native_scheme
;
}
if
(
!
WinHttpAddRequestHeaders
(
request
,
wide
,
(
ULONG
)
-
1L
,
WINHTTP_ADDREQ_FLAG_ADD
))
{
if
((
mechanisms
&
GIT_WINHTTP_AUTH_NTLM
)
||
giterr_set
(
GITERR_OS
,
"failed to add a header to the request"
);
(
mechanisms
&
GIT_WINHTTP_AUTH_NEGOTIATE
))
{
goto
on_error
;
native_scheme
=
WINHTTP_AUTH_SCHEME_NTLM
;
}
else
if
(
mechanisms
&
GIT_WINHTTP_AUTH_BASIC
)
{
native_scheme
=
WINHTTP_AUTH_SCHEME_BASIC
;
}
else
{
giterr_set
(
GITERR_NET
,
"invalid authentication scheme"
);
return
-
1
;
}
}
error
=
0
;
return
_apply_userpass_credential
(
request
,
WINHTTP_AUTH_TARGET_SERVER
,
native_scheme
,
cred
);
on_error:
/* We were dealing with plaintext passwords, so clean up after ourselves a bit. */
if
(
wide
)
memset
(
wide
,
0x0
,
wide_len
*
sizeof
(
wchar_t
));
if
(
buf
.
size
)
memset
(
buf
.
ptr
,
0x0
,
buf
.
size
);
if
(
raw
.
size
)
memset
(
raw
.
ptr
,
0x0
,
raw
.
size
);
git__free
(
wide
);
git_buf_free
(
&
buf
);
git_buf_free
(
&
raw
);
return
error
;
}
}
static
int
apply_default_credentials
(
HINTERNET
request
)
static
int
apply_default_credentials
(
HINTERNET
request
,
int
mechanisms
)
{
{
/* Either the caller explicitly requested that default credentials be passed,
/* Either the caller explicitly requested that default credentials be passed,
* or our fallback credential callback was invoked and checked that the target
* or our fallback credential callback was invoked and checked that the target
...
@@ -177,6 +165,12 @@ static int apply_default_credentials(HINTERNET request)
...
@@ -177,6 +165,12 @@ static int apply_default_credentials(HINTERNET request)
* to Internet Explorer security zones, but in fact does not. */
* to Internet Explorer security zones, but in fact does not. */
DWORD
data
=
WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
;
DWORD
data
=
WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
;
if
((
mechanisms
&
GIT_WINHTTP_AUTH_NTLM
)
==
0
&&
(
mechanisms
&
GIT_WINHTTP_AUTH_NEGOTIATE
)
==
0
)
{
giterr_set
(
GITERR_NET
,
"invalid authentication scheme"
);
return
-
1
;
}
if
(
!
WinHttpSetOption
(
request
,
WINHTTP_OPTION_AUTOLOGON_POLICY
,
&
data
,
sizeof
(
DWORD
)))
if
(
!
WinHttpSetOption
(
request
,
WINHTTP_OPTION_AUTOLOGON_POLICY
,
&
data
,
sizeof
(
DWORD
)))
return
-
1
;
return
-
1
;
...
@@ -453,7 +447,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
...
@@ -453,7 +447,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
if
(
t
->
proxy_cred
)
{
if
(
t
->
proxy_cred
)
{
if
(
t
->
proxy_cred
->
credtype
==
GIT_CREDTYPE_USERPASS_PLAINTEXT
)
{
if
(
t
->
proxy_cred
->
credtype
==
GIT_CREDTYPE_USERPASS_PLAINTEXT
)
{
if
((
error
=
apply_
basic
_credential_proxy
(
s
->
request
,
t
->
proxy_cred
))
<
0
)
if
((
error
=
apply_
userpass
_credential_proxy
(
s
->
request
,
t
->
proxy_cred
))
<
0
)
goto
on_error
;
goto
on_error
;
}
}
}
}
...
@@ -550,13 +544,11 @@ static int winhttp_stream_connect(winhttp_stream *s)
...
@@ -550,13 +544,11 @@ static int winhttp_stream_connect(winhttp_stream *s)
/* If we have a credential on the subtransport, apply it to the request */
/* If we have a credential on the subtransport, apply it to the request */
if
(
t
->
cred
&&
if
(
t
->
cred
&&
t
->
cred
->
credtype
==
GIT_CREDTYPE_USERPASS_PLAINTEXT
&&
t
->
cred
->
credtype
==
GIT_CREDTYPE_USERPASS_PLAINTEXT
&&
t
->
auth_mechanism
==
GIT_WINHTTP_AUTH_BASIC
&&
apply_userpass_credential
(
s
->
request
,
t
->
auth_mechanisms
,
t
->
cred
)
<
0
)
apply_basic_credential
(
s
->
request
,
t
->
cred
)
<
0
)
goto
on_error
;
goto
on_error
;
else
if
(
t
->
cred
&&
else
if
(
t
->
cred
&&
t
->
cred
->
credtype
==
GIT_CREDTYPE_DEFAULT
&&
t
->
cred
->
credtype
==
GIT_CREDTYPE_DEFAULT
&&
t
->
auth_mechanism
==
GIT_WINHTTP_AUTH_NEGOTIATE
&&
apply_default_credentials
(
s
->
request
,
t
->
auth_mechanisms
)
<
0
)
apply_default_credentials
(
s
->
request
)
<
0
)
goto
on_error
;
goto
on_error
;
/* If no other credentials have been applied and the URL has username and
/* If no other credentials have been applied and the URL has username and
...
@@ -565,7 +557,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
...
@@ -565,7 +557,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
if
(
!
t
->
url_cred
&&
if
(
!
t
->
url_cred
&&
git_cred_userpass_plaintext_new
(
&
t
->
url_cred
,
t
->
connection_data
.
user
,
t
->
connection_data
.
pass
)
<
0
)
git_cred_userpass_plaintext_new
(
&
t
->
url_cred
,
t
->
connection_data
.
user
,
t
->
connection_data
.
pass
)
<
0
)
goto
on_error
;
goto
on_error
;
if
(
apply_
basic_credential
(
s
->
request
,
t
->
url_cred
)
<
0
)
if
(
apply_
userpass_credential
(
s
->
request
,
GIT_WINHTTP_AUTH_BASIC
,
t
->
url_cred
)
<
0
)
goto
on_error
;
goto
on_error
;
}
}
...
@@ -585,12 +577,12 @@ on_error:
...
@@ -585,12 +577,12 @@ on_error:
static
int
parse_unauthorized_response
(
static
int
parse_unauthorized_response
(
HINTERNET
request
,
HINTERNET
request
,
int
*
allowed_types
,
int
*
allowed_types
,
int
*
a
uth_mechanism
)
int
*
a
llowed_mechanisms
)
{
{
DWORD
supported
,
first
,
target
;
DWORD
supported
,
first
,
target
;
*
allowed_types
=
0
;
*
allowed_types
=
0
;
*
a
uth_mechanism
=
0
;
*
a
llowed_mechanisms
=
0
;
/* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes().
/* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes().
* We can assume this was already done, since we know we are unauthorized.
* We can assume this was already done, since we know we are unauthorized.
...
@@ -600,15 +592,20 @@ static int parse_unauthorized_response(
...
@@ -600,15 +592,20 @@ static int parse_unauthorized_response(
return
-
1
;
return
-
1
;
}
}
if
(
WINHTTP_AUTH_SCHEME_
BASIC
&
supported
)
{
if
(
WINHTTP_AUTH_SCHEME_
NTLM
&
supported
)
{
*
allowed_types
|=
GIT_CREDTYPE_USERPASS_PLAINTEXT
;
*
allowed_types
|=
GIT_CREDTYPE_USERPASS_PLAINTEXT
;
*
auth_mechanism
=
GIT_WINHTTP_AUTH_BASIC
;
*
allowed_types
|=
GIT_CREDTYPE_DEFAULT
;
*
allowed_mechanisms
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
}
}
if
((
WINHTTP_AUTH_SCHEME_NTLM
&
supported
)
||
if
(
WINHTTP_AUTH_SCHEME_NEGOTIATE
&
supported
)
{
(
WINHTTP_AUTH_SCHEME_NEGOTIATE
&
supported
))
{
*
allowed_types
|=
GIT_CREDTYPE_DEFAULT
;
*
allowed_types
|=
GIT_CREDTYPE_DEFAULT
;
*
auth_mechanism
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
*
allowed_mechanisms
=
GIT_WINHTTP_AUTH_NEGOTIATE
;
}
if
(
WINHTTP_AUTH_SCHEME_BASIC
&
supported
)
{
*
allowed_types
|=
GIT_CREDTYPE_USERPASS_PLAINTEXT
;
*
allowed_mechanisms
|=
GIT_WINHTTP_AUTH_BASIC
;
}
}
return
0
;
return
0
;
...
@@ -1029,7 +1026,7 @@ replay:
...
@@ -1029,7 +1026,7 @@ replay:
if
(
status_code
==
HTTP_STATUS_PROXY_AUTH_REQ
)
{
if
(
status_code
==
HTTP_STATUS_PROXY_AUTH_REQ
)
{
int
allowed_types
;
int
allowed_types
;
if
(
parse_unauthorized_response
(
s
->
request
,
&
allowed_types
,
&
t
->
auth_mechanism
)
<
0
)
if
(
parse_unauthorized_response
(
s
->
request
,
&
allowed_types
,
&
t
->
auth_mechanism
s
)
<
0
)
return
-
1
;
return
-
1
;
/* TODO: extract the username from the url, no payload? */
/* TODO: extract the username from the url, no payload? */
...
@@ -1049,7 +1046,7 @@ replay:
...
@@ -1049,7 +1046,7 @@ replay:
if
(
HTTP_STATUS_DENIED
==
status_code
&&
get_verb
==
s
->
verb
)
{
if
(
HTTP_STATUS_DENIED
==
status_code
&&
get_verb
==
s
->
verb
)
{
int
allowed_types
;
int
allowed_types
;
if
(
parse_unauthorized_response
(
s
->
request
,
&
allowed_types
,
&
t
->
auth_mechanism
)
<
0
)
if
(
parse_unauthorized_response
(
s
->
request
,
&
allowed_types
,
&
t
->
auth_mechanism
s
)
<
0
)
return
-
1
;
return
-
1
;
if
(
allowed_types
)
{
if
(
allowed_types
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment