mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Added NTLM support.
This commit is contained in:
parent
8f0378df0b
commit
52ad80309f
3
AUTHORS
3
AUTHORS
@ -34,3 +34,6 @@ Mauro Tortonesi. Improved IPv6 support, adding support for dual
|
|||||||
family systems. Refactored and enhanced FTP IPv6 code.
|
family systems. Refactored and enhanced FTP IPv6 code.
|
||||||
|
|
||||||
Nicolas Schodet. Contributed to cookie code and documentation.
|
Nicolas Schodet. Contributed to cookie code and documentation.
|
||||||
|
|
||||||
|
Daniel Stenberg. NTLM authentication in http-ntlm.c and http-ntlm.h
|
||||||
|
originally written curl donated for use in GNU Wget.
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
2005-04-06 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* configure.in: Allow the user to disable NTLM authorization.
|
||||||
|
Make sure NTLM is disabled if OpenSSL is unavailable. If NTLM is
|
||||||
|
*explicitly* requested and OpenSSL is unavailable, abort.
|
||||||
|
|
||||||
|
* configure.in: Renamed USE_* to ENABLE_*.
|
||||||
|
|
||||||
2005-03-23 Hrvoje Niksic <hniksic@xemacs.org>
|
2005-03-23 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* po/POTFILES.in: Removed headers.c and rbuf.c.
|
* po/POTFILES.in: Removed headers.c and rbuf.c.
|
||||||
|
@ -182,7 +182,7 @@ $(srcdir)/configure: configure.in aclocal.m4
|
|||||||
# autoheader might not change config.h.in, so touch a stamp file.
|
# autoheader might not change config.h.in, so touch a stamp file.
|
||||||
$(srcdir)/src/config.h.in: stamp-h.in
|
$(srcdir)/src/config.h.in: stamp-h.in
|
||||||
$(srcdir)/stamp-h.in: configure.in aclocal.m4
|
$(srcdir)/stamp-h.in: configure.in aclocal.m4
|
||||||
cd $(srcdir) && autoheader
|
-cd $(srcdir) && autoheader
|
||||||
echo timestamp > $(srcdir)/stamp-h.in
|
echo timestamp > $(srcdir)/stamp-h.in
|
||||||
|
|
||||||
src/config.h: stamp-h
|
src/config.h: stamp-h
|
||||||
|
36
configure.in
36
configure.in
@ -58,16 +58,20 @@ AC_ARG_WITH(ssl,
|
|||||||
|
|
||||||
AC_ARG_ENABLE(opie,
|
AC_ARG_ENABLE(opie,
|
||||||
[ --disable-opie disable support for opie or s/key FTP login],
|
[ --disable-opie disable support for opie or s/key FTP login],
|
||||||
USE_OPIE=$enableval, USE_OPIE=yes)
|
ENABLE_OPIE=$enableval, ENABLE_OPIE=yes)
|
||||||
test x"${USE_OPIE}" = xyes && AC_DEFINE([USE_OPIE], 1,
|
test x"${ENABLE_OPIE}" = xyes && AC_DEFINE([ENABLE_OPIE], 1,
|
||||||
[Define if you want the Opie support for FTP compiled in.])
|
[Define if you want the Opie support for FTP compiled in.])
|
||||||
|
|
||||||
AC_ARG_ENABLE(digest,
|
AC_ARG_ENABLE(digest,
|
||||||
[ --disable-digest disable support for HTTP digest authorization],
|
[ --disable-digest disable support for HTTP digest authorization],
|
||||||
USE_DIGEST=$enableval, USE_DIGEST=yes)
|
ENABLE_DIGEST=$enableval, ENABLE_DIGEST=yes)
|
||||||
test x"${USE_DIGEST}" = xyes && AC_DEFINE([USE_DIGEST], 1,
|
test x"${ENABLE_DIGEST}" = xyes && AC_DEFINE([ENABLE_DIGEST], 1,
|
||||||
[Define if you want the HTTP Digest Authorization compiled in.])
|
[Define if you want the HTTP Digest Authorization compiled in.])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(ntlm,
|
||||||
|
[ --disable-ntlm disable support for NTLM authorization],
|
||||||
|
[ENABLE_NTLM=$enableval], [ENABLE_NTLM=auto])
|
||||||
|
|
||||||
AC_ARG_ENABLE(debug,
|
AC_ARG_ENABLE(debug,
|
||||||
[ --disable-debug disable support for debugging output],
|
[ --disable-debug disable support for debugging output],
|
||||||
ENABLE_DEBUG=$enableval, ENABLE_DEBUG=yes)
|
ENABLE_DEBUG=$enableval, ENABLE_DEBUG=yes)
|
||||||
@ -76,11 +80,11 @@ test x"${ENABLE_DEBUG}" = xyes && AC_DEFINE([ENABLE_DEBUG], 1,
|
|||||||
|
|
||||||
wget_need_md5=no
|
wget_need_md5=no
|
||||||
|
|
||||||
case "${USE_OPIE}${USE_DIGEST}" in
|
case "${ENABLE_OPIE}${ENABLE_DIGEST}" in
|
||||||
*yes*)
|
*yes*)
|
||||||
wget_need_md5=yes
|
wget_need_md5=yes
|
||||||
esac
|
esac
|
||||||
if test x"$USE_OPIE" = xyes; then
|
if test x"$ENABLE_OPIE" = xyes; then
|
||||||
OPIE_OBJ='ftp-opie$o'
|
OPIE_OBJ='ftp-opie$o'
|
||||||
fi
|
fi
|
||||||
AC_SUBST(OPIE_OBJ)
|
AC_SUBST(OPIE_OBJ)
|
||||||
@ -413,6 +417,26 @@ main(){return 0;}
|
|||||||
CPPFLAGS=$wget_save_CPPFLAGS
|
CPPFLAGS=$wget_save_CPPFLAGS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl Enable NTLM if requested and if SSL is available.
|
||||||
|
NTLM_OBJ=''
|
||||||
|
if test x"$ssl_success" = xyes
|
||||||
|
then
|
||||||
|
if test x"$ENABLE_NTLM" != xno
|
||||||
|
then
|
||||||
|
AC_DEFINE([ENABLE_NTLM], 1,
|
||||||
|
[Define if you want the NTLM authorization support compiled in.])
|
||||||
|
NTLM_OBJ='http-ntlm$o'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dnl If SSL is unavailable and the user explicitly requested NTLM,
|
||||||
|
dnl abort.
|
||||||
|
if test x"$ENABLE_NTLM" = xyes
|
||||||
|
then
|
||||||
|
AC_MSG_ERROR([NTLM authorization requested and OpenSSL not found; aborting])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AC_SUBST(NTLM_OBJ)
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl Find an md5 implementation.
|
dnl Find an md5 implementation.
|
||||||
dnl
|
dnl
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
2005-04-06 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* http.c (pconn): Include NTLM data, which is per-connection.
|
||||||
|
(known_authentication_scheme_p): Recognize NTLM authorization.
|
||||||
|
(create_authorization_line): Call ntlm_input and ntlm_output.
|
||||||
|
|
||||||
|
* http-ntlm.c: New file, donated by Daniel Stenberg and originally
|
||||||
|
written for curl, heavily modified for Wget.
|
||||||
|
|
||||||
|
* utils.c (base64_encode): Relocated from http.c, since it is now
|
||||||
|
used by http-ntlm.c, and will possibly be used elsewhere.
|
||||||
|
(base64_decode): New function, originally based on code from GNU
|
||||||
|
recode.
|
||||||
|
|
||||||
|
2005-04-02 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* ftp.c (ftp_loop): Ditto.
|
||||||
|
|
||||||
|
* ftp-basic.c (ftp_pasv): Use the xzero shorthand for memset(0).
|
||||||
|
(ftp_lpsv): Ditto.
|
||||||
|
|
||||||
2005-04-05 Mauro Tortonesi <mauro@ferrara.linux.it>
|
2005-04-05 Mauro Tortonesi <mauro@ferrara.linux.it>
|
||||||
|
|
||||||
* Makefile.in: removed string_t.c from list of source files.
|
* Makefile.in: removed string_t.c from list of source files.
|
||||||
|
@ -69,13 +69,14 @@ ETAGS = etags
|
|||||||
ALLOCA = @ALLOCA@
|
ALLOCA = @ALLOCA@
|
||||||
MD5_OBJ = @MD5_OBJ@
|
MD5_OBJ = @MD5_OBJ@
|
||||||
OPIE_OBJ = @OPIE_OBJ@
|
OPIE_OBJ = @OPIE_OBJ@
|
||||||
|
NTLM_OBJ = @NTLM_OBJ@
|
||||||
SSL_OBJ = @SSL_OBJ@
|
SSL_OBJ = @SSL_OBJ@
|
||||||
GETOPT_OBJ = @GETOPT_OBJ@
|
GETOPT_OBJ = @GETOPT_OBJ@
|
||||||
|
|
||||||
OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \
|
OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \
|
||||||
ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \
|
ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \
|
||||||
host$o html-parse$o html-url$o http$o init$o \
|
host$o html-parse$o html-url$o http$o $(NTLM_OBJ) init$o \
|
||||||
log$o main$o $(MD5_OBJ) netrc$o progress$o recur$o \
|
log$o main$o $(MD5_OBJ) netrc$o progress$o recur$o \
|
||||||
res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \
|
res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \
|
||||||
utils$o version$o xmalloc$o
|
utils$o version$o xmalloc$o
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ ftp_login (int csock, const char *acc, const char *pass)
|
|||||||
xfree (respline);
|
xfree (respline);
|
||||||
return FTPLOGREFUSED;
|
return FTPLOGREFUSED;
|
||||||
}
|
}
|
||||||
#ifdef USE_OPIE
|
#ifdef ENABLE_OPIE
|
||||||
{
|
{
|
||||||
static const char *skey_head[] = {
|
static const char *skey_head[] = {
|
||||||
"331 s/key ",
|
"331 s/key ",
|
||||||
@ -195,7 +195,7 @@ ftp_login (int csock, const char *acc, const char *pass)
|
|||||||
pass = skey_response (skey_sequence, seed, pass);
|
pass = skey_response (skey_sequence, seed, pass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* USE_OPIE */
|
#endif /* ENABLE_OPIE */
|
||||||
xfree (respline);
|
xfree (respline);
|
||||||
/* Send PASS password. */
|
/* Send PASS password. */
|
||||||
request = ftp_request ("PASS", pass);
|
request = ftp_request ("PASS", pass);
|
||||||
|
@ -62,7 +62,7 @@ uerr_t ftp_syst PARAMS ((int, enum stype *));
|
|||||||
uerr_t ftp_pwd PARAMS ((int, char **));
|
uerr_t ftp_pwd PARAMS ((int, char **));
|
||||||
uerr_t ftp_size PARAMS ((int, const char *, wgint *));
|
uerr_t ftp_size PARAMS ((int, const char *, wgint *));
|
||||||
|
|
||||||
#ifdef USE_OPIE
|
#ifdef ENABLE_OPIE
|
||||||
const char *skey_response PARAMS ((int, const char *, const char *));
|
const char *skey_response PARAMS ((int, const char *, const char *));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
561
src/http-ntlm.c
Normal file
561
src/http-ntlm.c
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
/* NTLM code.
|
||||||
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
Donated by Daniel Stenberg.
|
||||||
|
|
||||||
|
This file is part of GNU Wget.
|
||||||
|
|
||||||
|
GNU Wget is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
GNU Wget is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Wget; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
In addition, as a special exception, the Free Software Foundation
|
||||||
|
gives permission to link the code of its release of Wget with the
|
||||||
|
OpenSSL project's "OpenSSL" library (or with modified versions of it
|
||||||
|
that use the same license as the "OpenSSL" library), and distribute
|
||||||
|
the linked executables. You must obey the GNU General Public License
|
||||||
|
in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
modify this file, you may extend this exception to your version of the
|
||||||
|
file, but you are not obligated to do so. If you do not wish to do
|
||||||
|
so, delete this exception statement from your version. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/* NTLM details:
|
||||||
|
|
||||||
|
http://davenport.sourceforge.net/ntlm.html
|
||||||
|
http://www.innovation.ch/java/ntlm.html
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -- WIN32 approved -- */
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# include <strings.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <openssl/des.h>
|
||||||
|
#include <openssl/md4.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
#include "wget.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "http-ntlm.h"
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x00907001L
|
||||||
|
#define DES_key_schedule des_key_schedule
|
||||||
|
#define DES_cblock des_cblock
|
||||||
|
#define DES_set_odd_parity des_set_odd_parity
|
||||||
|
#define DES_set_key des_set_key
|
||||||
|
#define DES_ecb_encrypt des_ecb_encrypt
|
||||||
|
|
||||||
|
/* This is how things were done in the old days */
|
||||||
|
#define DESKEY(x) x
|
||||||
|
#define DESKEYARG(x) x
|
||||||
|
#else
|
||||||
|
/* Modern version */
|
||||||
|
#define DESKEYARG(x) *x
|
||||||
|
#define DESKEY(x) &x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define this to make the type-3 message include the NT response message */
|
||||||
|
#undef USE_NTRESPONSES
|
||||||
|
|
||||||
|
/* Flag bits definitions available at on
|
||||||
|
http://davenport.sourceforge.net/ntlm.html */
|
||||||
|
|
||||||
|
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
|
||||||
|
#define NTLMFLAG_REQUEST_TARGET (1<<2)
|
||||||
|
/* unknown (1<<3) */
|
||||||
|
#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
|
||||||
|
/* unknown (1<<10) */
|
||||||
|
/* unknown (1<<11) */
|
||||||
|
#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
|
||||||
|
#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
|
||||||
|
#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
|
||||||
|
#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
|
||||||
|
#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
|
||||||
|
#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
|
||||||
|
#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
|
||||||
|
/* unknown (1<24) */
|
||||||
|
/* unknown (1<25) */
|
||||||
|
/* unknown (1<26) */
|
||||||
|
/* unknown (1<27) */
|
||||||
|
/* unknown (1<28) */
|
||||||
|
#define NTLMFLAG_NEGOTIATE_128 (1<<29)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
|
||||||
|
#define NTLMFLAG_NEGOTIATE_56 (1<<31)
|
||||||
|
|
||||||
|
/*
|
||||||
|
(*) = A "security buffer" is a triplet consisting of two shorts and one
|
||||||
|
long:
|
||||||
|
|
||||||
|
1. a 'short' containing the length of the buffer in bytes
|
||||||
|
2. a 'short' containing the allocated space for the buffer in bytes
|
||||||
|
3. a 'long' containing the offset to the start of the buffer from the
|
||||||
|
beginning of the NTLM message, in bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* return 1 on success, 0 otherwise */
|
||||||
|
int ntlm_input (struct ntlmdata *ntlm, const char *header)
|
||||||
|
{
|
||||||
|
if (0 != strncmp (header, "NTLM", 4))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
header += 4;
|
||||||
|
while (*header && ISSPACE(*header))
|
||||||
|
header++;
|
||||||
|
|
||||||
|
if (*header)
|
||||||
|
{
|
||||||
|
/* We got a type-2 message here:
|
||||||
|
|
||||||
|
Index Description Content
|
||||||
|
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
|
||||||
|
(0x4e544c4d53535000)
|
||||||
|
8 NTLM Message Type long (0x02000000)
|
||||||
|
12 Target Name security buffer(*)
|
||||||
|
20 Flags long
|
||||||
|
24 Challenge 8 bytes
|
||||||
|
(32) Context (optional) 8 bytes (two consecutive longs)
|
||||||
|
(40) Target Information (optional) security buffer(*)
|
||||||
|
32 (48) start of data block
|
||||||
|
*/
|
||||||
|
int size;
|
||||||
|
unsigned char *buffer = (unsigned char *) alloca (strlen (header));
|
||||||
|
|
||||||
|
size = base64_decode (header, buffer);
|
||||||
|
if (size < 0)
|
||||||
|
return 0; /* malformed base64 from server */
|
||||||
|
|
||||||
|
ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
|
||||||
|
|
||||||
|
if (size >= 48)
|
||||||
|
/* the nonce of interest is index [24 .. 31], 8 bytes */
|
||||||
|
memcpy (ntlm->nonce, &buffer[24], 8);
|
||||||
|
|
||||||
|
/* at index decimal 20, there's a 32bit NTLM flag field */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ntlm->state >= NTLMSTATE_TYPE1)
|
||||||
|
return 0; /* this is an error */
|
||||||
|
|
||||||
|
ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
|
||||||
|
* key schedule ks is also set.
|
||||||
|
*/
|
||||||
|
static void setup_des_key(unsigned char *key_56,
|
||||||
|
DES_key_schedule DESKEYARG(ks))
|
||||||
|
{
|
||||||
|
DES_cblock key;
|
||||||
|
|
||||||
|
key[0] = key_56[0];
|
||||||
|
key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
|
||||||
|
key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
|
||||||
|
key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
|
||||||
|
key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
|
||||||
|
key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
|
||||||
|
key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
|
||||||
|
key[7] = (key_56[6] << 1) & 0xFF;
|
||||||
|
|
||||||
|
DES_set_odd_parity(&key);
|
||||||
|
DES_set_key(&key, ks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
|
||||||
|
* 8 byte plaintext is encrypted with each key and the resulting 24
|
||||||
|
* bytes are stored in the results array.
|
||||||
|
*/
|
||||||
|
static void calc_resp(unsigned char *keys,
|
||||||
|
unsigned char *plaintext,
|
||||||
|
unsigned char *results)
|
||||||
|
{
|
||||||
|
DES_key_schedule ks;
|
||||||
|
|
||||||
|
setup_des_key(keys, DESKEY(ks));
|
||||||
|
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
|
||||||
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
|
||||||
|
setup_des_key(keys+7, DESKEY(ks));
|
||||||
|
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
|
||||||
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
|
||||||
|
setup_des_key(keys+14, DESKEY(ks));
|
||||||
|
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
|
||||||
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up lanmanager and nt hashed passwords
|
||||||
|
*/
|
||||||
|
static void mkhash(const char *password,
|
||||||
|
unsigned char *nonce, /* 8 bytes */
|
||||||
|
unsigned char *lmresp /* must fit 0x18 bytes */
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
, unsigned char *ntresp /* must fit 0x18 bytes */
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned char lmbuffer[21];
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
unsigned char ntbuffer[21];
|
||||||
|
#endif
|
||||||
|
unsigned char *pw;
|
||||||
|
static const unsigned char magic[] = {
|
||||||
|
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
int len = strlen(password);
|
||||||
|
|
||||||
|
/* make it fit at least 14 bytes */
|
||||||
|
pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
|
||||||
|
|
||||||
|
if (len > 14)
|
||||||
|
len = 14;
|
||||||
|
|
||||||
|
for (i=0; i<len; i++)
|
||||||
|
pw[i] = TOUPPER (password[i]);
|
||||||
|
|
||||||
|
for (; i<14; i++)
|
||||||
|
pw[i] = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
/* create LanManager hashed password */
|
||||||
|
DES_key_schedule ks;
|
||||||
|
|
||||||
|
setup_des_key(pw, DESKEY(ks));
|
||||||
|
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
|
||||||
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
|
||||||
|
setup_des_key(pw+7, DESKEY(ks));
|
||||||
|
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
|
||||||
|
DESKEY(ks), DES_ENCRYPT);
|
||||||
|
|
||||||
|
memset(lmbuffer+16, 0, 5);
|
||||||
|
}
|
||||||
|
/* create LM responses */
|
||||||
|
calc_resp(lmbuffer, nonce, lmresp);
|
||||||
|
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
{
|
||||||
|
/* create NT hashed password */
|
||||||
|
MD4_CTX MD4;
|
||||||
|
|
||||||
|
len = strlen(password);
|
||||||
|
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
pw[2*i] = password[i];
|
||||||
|
pw[2*i+1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MD4_Init(&MD4);
|
||||||
|
MD4_Update(&MD4, pw, 2*len);
|
||||||
|
MD4_Final(ntbuffer, &MD4);
|
||||||
|
|
||||||
|
memset(ntbuffer+16, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
calc_resp(ntbuffer, nonce, ntresp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
|
||||||
|
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
|
||||||
|
(((x) >>16)&0xff), ((x)>>24)
|
||||||
|
|
||||||
|
/* this is for creating ntlm header output */
|
||||||
|
char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
|
||||||
|
int *ready)
|
||||||
|
{
|
||||||
|
const char *domain=""; /* empty */
|
||||||
|
const char *host=""; /* empty */
|
||||||
|
int domlen=strlen(domain);
|
||||||
|
int hostlen = strlen(host);
|
||||||
|
int hostoff; /* host name offset */
|
||||||
|
int domoff; /* domain name offset */
|
||||||
|
int size;
|
||||||
|
char *base64;
|
||||||
|
unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */
|
||||||
|
|
||||||
|
/* point to the address of the pointer that holds the string to sent to the
|
||||||
|
server, which is for a plain host or for a HTTP proxy */
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
*ready = 0;
|
||||||
|
|
||||||
|
/* not set means empty */
|
||||||
|
if(!user)
|
||||||
|
user="";
|
||||||
|
|
||||||
|
if(!passwd)
|
||||||
|
passwd="";
|
||||||
|
|
||||||
|
switch(ntlm->state) {
|
||||||
|
case NTLMSTATE_TYPE1:
|
||||||
|
default: /* for the weird cases we (re)start here */
|
||||||
|
hostoff = 32;
|
||||||
|
domoff = hostoff + hostlen;
|
||||||
|
|
||||||
|
/* Create and send a type-1 message:
|
||||||
|
|
||||||
|
Index Description Content
|
||||||
|
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
|
||||||
|
(0x4e544c4d53535000)
|
||||||
|
8 NTLM Message Type long (0x01000000)
|
||||||
|
12 Flags long
|
||||||
|
16 Supplied Domain security buffer(*)
|
||||||
|
24 Supplied Workstation security buffer(*)
|
||||||
|
32 start of data block
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
|
||||||
|
"\x01%c%c%c" /* 32-bit type = 1 */
|
||||||
|
"%c%c%c%c" /* 32-bit NTLM flag field */
|
||||||
|
"%c%c" /* domain length */
|
||||||
|
"%c%c" /* domain allocated space */
|
||||||
|
"%c%c" /* domain name offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
"%c%c" /* host length */
|
||||||
|
"%c%c" /* host allocated space */
|
||||||
|
"%c%c" /* host name offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
"%s" /* host name */
|
||||||
|
"%s", /* domain string */
|
||||||
|
0, /* trailing zero */
|
||||||
|
0,0,0, /* part of type-1 long */
|
||||||
|
|
||||||
|
LONGQUARTET(
|
||||||
|
NTLMFLAG_NEGOTIATE_OEM| /* 2 */
|
||||||
|
NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
|
||||||
|
/* equals 0x0202 */
|
||||||
|
),
|
||||||
|
SHORTPAIR(domlen),
|
||||||
|
SHORTPAIR(domlen),
|
||||||
|
SHORTPAIR(domoff),
|
||||||
|
0,0,
|
||||||
|
SHORTPAIR(hostlen),
|
||||||
|
SHORTPAIR(hostlen),
|
||||||
|
SHORTPAIR(hostoff),
|
||||||
|
0,0,
|
||||||
|
host, domain);
|
||||||
|
|
||||||
|
/* initial packet length */
|
||||||
|
size = 32 + hostlen + domlen;
|
||||||
|
|
||||||
|
base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
|
||||||
|
base64_encode (ntlmbuf, base64, size);
|
||||||
|
|
||||||
|
output = concat_strings ("NTLM ", base64, (char *) 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NTLMSTATE_TYPE2:
|
||||||
|
/* We received the type-2 already, create a type-3 message:
|
||||||
|
|
||||||
|
Index Description Content
|
||||||
|
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
|
||||||
|
(0x4e544c4d53535000)
|
||||||
|
8 NTLM Message Type long (0x03000000)
|
||||||
|
12 LM/LMv2 Response security buffer(*)
|
||||||
|
20 NTLM/NTLMv2 Response security buffer(*)
|
||||||
|
28 Domain Name security buffer(*)
|
||||||
|
36 User Name security buffer(*)
|
||||||
|
44 Workstation Name security buffer(*)
|
||||||
|
(52) Session Key (optional) security buffer(*)
|
||||||
|
(60) Flags (optional) long
|
||||||
|
52 (64) start of data block
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
int lmrespoff;
|
||||||
|
int ntrespoff;
|
||||||
|
int useroff;
|
||||||
|
unsigned char lmresp[0x18]; /* fixed-size */
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
unsigned char ntresp[0x18]; /* fixed-size */
|
||||||
|
#endif
|
||||||
|
const char *usr;
|
||||||
|
int userlen;
|
||||||
|
|
||||||
|
usr = strchr(user, '\\');
|
||||||
|
if(!usr)
|
||||||
|
usr = strchr(user, '/');
|
||||||
|
|
||||||
|
if (usr) {
|
||||||
|
domain = usr;
|
||||||
|
domlen = usr - domain;
|
||||||
|
usr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usr = user;
|
||||||
|
userlen = strlen(usr);
|
||||||
|
|
||||||
|
mkhash(passwd, &ntlm->nonce[0], lmresp
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
, ntresp
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
domoff = 64; /* always */
|
||||||
|
useroff = domoff + domlen;
|
||||||
|
hostoff = useroff + userlen;
|
||||||
|
lmrespoff = hostoff + hostlen;
|
||||||
|
ntrespoff = lmrespoff + 0x18;
|
||||||
|
|
||||||
|
/* Create the big type-3 message binary blob */
|
||||||
|
size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
|
||||||
|
"NTLMSSP%c"
|
||||||
|
"\x03%c%c%c" /* type-3, 32 bits */
|
||||||
|
|
||||||
|
"%c%c%c%c" /* LanManager length + allocated space */
|
||||||
|
"%c%c" /* LanManager offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
"%c%c" /* NT-response length */
|
||||||
|
"%c%c" /* NT-response allocated space */
|
||||||
|
"%c%c" /* NT-response offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
"%c%c" /* domain length */
|
||||||
|
"%c%c" /* domain allocated space */
|
||||||
|
"%c%c" /* domain name offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
"%c%c" /* user length */
|
||||||
|
"%c%c" /* user allocated space */
|
||||||
|
"%c%c" /* user offset */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
"%c%c" /* host length */
|
||||||
|
"%c%c" /* host allocated space */
|
||||||
|
"%c%c" /* host offset */
|
||||||
|
"%c%c%c%c%c%c" /* 6 zeroes */
|
||||||
|
|
||||||
|
"\xff\xff" /* message length */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
"\x01\x82" /* flags */
|
||||||
|
"%c%c" /* 2 zeroes */
|
||||||
|
|
||||||
|
/* domain string */
|
||||||
|
/* user string */
|
||||||
|
/* host string */
|
||||||
|
/* LanManager response */
|
||||||
|
/* NT response */
|
||||||
|
,
|
||||||
|
0, /* zero termination */
|
||||||
|
0,0,0, /* type-3 long, the 24 upper bits */
|
||||||
|
|
||||||
|
SHORTPAIR(0x18), /* LanManager response length, twice */
|
||||||
|
SHORTPAIR(0x18),
|
||||||
|
SHORTPAIR(lmrespoff),
|
||||||
|
0x0, 0x0,
|
||||||
|
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
SHORTPAIR(0x18), /* NT-response length, twice */
|
||||||
|
SHORTPAIR(0x18),
|
||||||
|
#else
|
||||||
|
0x0, 0x0,
|
||||||
|
0x0, 0x0,
|
||||||
|
#endif
|
||||||
|
SHORTPAIR(ntrespoff),
|
||||||
|
0x0, 0x0,
|
||||||
|
|
||||||
|
SHORTPAIR(domlen),
|
||||||
|
SHORTPAIR(domlen),
|
||||||
|
SHORTPAIR(domoff),
|
||||||
|
0x0, 0x0,
|
||||||
|
|
||||||
|
SHORTPAIR(userlen),
|
||||||
|
SHORTPAIR(userlen),
|
||||||
|
SHORTPAIR(useroff),
|
||||||
|
0x0, 0x0,
|
||||||
|
|
||||||
|
SHORTPAIR(hostlen),
|
||||||
|
SHORTPAIR(hostlen),
|
||||||
|
SHORTPAIR(hostoff),
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
|
||||||
|
0x0, 0x0,
|
||||||
|
|
||||||
|
0x0, 0x0);
|
||||||
|
|
||||||
|
/* size is now 64 */
|
||||||
|
size=64;
|
||||||
|
ntlmbuf[62]=ntlmbuf[63]=0;
|
||||||
|
|
||||||
|
memcpy(&ntlmbuf[size], domain, domlen);
|
||||||
|
size += domlen;
|
||||||
|
|
||||||
|
memcpy(&ntlmbuf[size], usr, userlen);
|
||||||
|
size += userlen;
|
||||||
|
|
||||||
|
/* we append the binary hashes to the end of the blob */
|
||||||
|
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
||||||
|
memcpy(&ntlmbuf[size], lmresp, 0x18);
|
||||||
|
size += 0x18;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_NTRESPONSES
|
||||||
|
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
||||||
|
memcpy(&ntlmbuf[size], ntresp, 0x18);
|
||||||
|
size += 0x18;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ntlmbuf[56] = size & 0xff;
|
||||||
|
ntlmbuf[57] = size >> 8;
|
||||||
|
|
||||||
|
/* convert the binary blob into base64 */
|
||||||
|
base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
|
||||||
|
base64_encode (ntlmbuf, base64, size);
|
||||||
|
|
||||||
|
output = concat_strings ("NTLM ", base64, (char *) 0);
|
||||||
|
|
||||||
|
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
|
||||||
|
*ready = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NTLMSTATE_TYPE3:
|
||||||
|
/* connection is already authenticated,
|
||||||
|
* don't send a header in future requests */
|
||||||
|
*ready = 1;
|
||||||
|
output = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
52
src/http-ntlm.h
Normal file
52
src/http-ntlm.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef __HTTP_NTLM_H
|
||||||
|
#define __HTTP_NTLM_H
|
||||||
|
/* Declarations for http_ntlm.c
|
||||||
|
Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Wget.
|
||||||
|
|
||||||
|
GNU Wget is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
GNU Wget is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Wget; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
In addition, as a special exception, the Free Software Foundation
|
||||||
|
gives permission to link the code of its release of Wget with the
|
||||||
|
OpenSSL project's "OpenSSL" library (or with modified versions of it
|
||||||
|
that use the same license as the "OpenSSL" library), and distribute
|
||||||
|
the linked executables. You must obey the GNU General Public License
|
||||||
|
in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
modify this file, you may extend this exception to your version of the
|
||||||
|
file, but you are not obligated to do so. If you do not wish to do
|
||||||
|
so, delete this exception statement from your version. */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NTLMSTATE_NONE,
|
||||||
|
NTLMSTATE_TYPE1,
|
||||||
|
NTLMSTATE_TYPE2,
|
||||||
|
NTLMSTATE_TYPE3,
|
||||||
|
NTLMSTATE_LAST
|
||||||
|
} wgetntlm;
|
||||||
|
|
||||||
|
/* Struct used for NTLM challenge-response authentication */
|
||||||
|
struct ntlmdata {
|
||||||
|
wgetntlm state;
|
||||||
|
unsigned char nonce[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* this is for ntlm header input */
|
||||||
|
int ntlm_input PARAMS ((struct ntlmdata *, const char *));
|
||||||
|
|
||||||
|
/* this is for creating ntlm header output */
|
||||||
|
char *ntlm_output PARAMS ((struct ntlmdata *,
|
||||||
|
const char *, const char *, int *));
|
||||||
|
#endif
|
78
src/http.c
78
src/http.c
@ -65,9 +65,12 @@ extern int errno;
|
|||||||
#include "netrc.h"
|
#include "netrc.h"
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
# include "gen_sslfunc.h"
|
# include "gen_sslfunc.h"
|
||||||
#endif /* HAVE_SSL */
|
#endif
|
||||||
|
#ifdef ENABLE_NTLM
|
||||||
|
# include "http-ntlm.h"
|
||||||
|
#endif
|
||||||
#include "cookies.h"
|
#include "cookies.h"
|
||||||
#ifdef USE_DIGEST
|
#ifdef ENABLE_DIGEST
|
||||||
# include "gen-md5.h"
|
# include "gen-md5.h"
|
||||||
#endif
|
#endif
|
||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
@ -824,6 +827,11 @@ static struct {
|
|||||||
|
|
||||||
/* Whether a ssl handshake has occoured on this connection. */
|
/* Whether a ssl handshake has occoured on this connection. */
|
||||||
int ssl;
|
int ssl;
|
||||||
|
|
||||||
|
#ifdef ENABLE_NTLM
|
||||||
|
/* NTLM data of the current connection. */
|
||||||
|
struct ntlmdata ntlm;
|
||||||
|
#endif
|
||||||
} pconn;
|
} pconn;
|
||||||
|
|
||||||
/* Mark the persistent connection as invalid and free the resources it
|
/* Mark the persistent connection as invalid and free the resources it
|
||||||
@ -2574,47 +2582,6 @@ http_atotm (const char *time_string)
|
|||||||
consisting of answering to the server's challenge with the proper
|
consisting of answering to the server's challenge with the proper
|
||||||
MD5 digests. */
|
MD5 digests. */
|
||||||
|
|
||||||
/* How many bytes it will take to store LEN bytes in base64. */
|
|
||||||
#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
|
|
||||||
|
|
||||||
/* Encode the string S of length LENGTH to base64 format and place it
|
|
||||||
to STORE. STORE will be 0-terminated, and must point to a writable
|
|
||||||
buffer of at least 1+BASE64_LENGTH(length) bytes. */
|
|
||||||
static void
|
|
||||||
base64_encode (const char *s, char *store, int length)
|
|
||||||
{
|
|
||||||
/* Conversion table. */
|
|
||||||
static char tbl[64] = {
|
|
||||||
'A','B','C','D','E','F','G','H',
|
|
||||||
'I','J','K','L','M','N','O','P',
|
|
||||||
'Q','R','S','T','U','V','W','X',
|
|
||||||
'Y','Z','a','b','c','d','e','f',
|
|
||||||
'g','h','i','j','k','l','m','n',
|
|
||||||
'o','p','q','r','s','t','u','v',
|
|
||||||
'w','x','y','z','0','1','2','3',
|
|
||||||
'4','5','6','7','8','9','+','/'
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
unsigned char *p = (unsigned char *)store;
|
|
||||||
|
|
||||||
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
|
|
||||||
for (i = 0; i < length; i += 3)
|
|
||||||
{
|
|
||||||
*p++ = tbl[s[0] >> 2];
|
|
||||||
*p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
|
|
||||||
*p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
|
|
||||||
*p++ = tbl[s[2] & 0x3f];
|
|
||||||
s += 3;
|
|
||||||
}
|
|
||||||
/* Pad the result if necessary... */
|
|
||||||
if (i == length + 1)
|
|
||||||
*(p - 1) = '=';
|
|
||||||
else if (i == length + 2)
|
|
||||||
*(p - 1) = *(p - 2) = '=';
|
|
||||||
/* ...and zero-terminate it. */
|
|
||||||
*p = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the authentication header contents for the `Basic' scheme.
|
/* Create the authentication header contents for the `Basic' scheme.
|
||||||
This is done by encoding the string `USER:PASS' in base64 and
|
This is done by encoding the string `USER:PASS' in base64 and
|
||||||
prepending `HEADER: Basic ' to it. */
|
prepending `HEADER: Basic ' to it. */
|
||||||
@ -2639,7 +2606,7 @@ basic_authentication_encode (const char *user, const char *passwd)
|
|||||||
++(x); \
|
++(x); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifdef USE_DIGEST
|
#ifdef ENABLE_DIGEST
|
||||||
/* Parse HTTP `WWW-Authenticate:' header. AU points to the beginning
|
/* Parse HTTP `WWW-Authenticate:' header. AU points to the beginning
|
||||||
of a field in such a header. If the field is the one specified by
|
of a field in such a header. If the field is the one specified by
|
||||||
ATTR_NAME ("realm", "opaque", and "nonce" are used by the current
|
ATTR_NAME ("realm", "opaque", and "nonce" are used by the current
|
||||||
@ -2825,7 +2792,7 @@ username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif /* USE_DIGEST */
|
#endif /* ENABLE_DIGEST */
|
||||||
|
|
||||||
|
|
||||||
#define BEGINS_WITH(line, string_constant) \
|
#define BEGINS_WITH(line, string_constant) \
|
||||||
@ -2837,8 +2804,13 @@ static int
|
|||||||
known_authentication_scheme_p (const char *au)
|
known_authentication_scheme_p (const char *au)
|
||||||
{
|
{
|
||||||
return BEGINS_WITH (au, "Basic")
|
return BEGINS_WITH (au, "Basic")
|
||||||
|
#ifdef ENABLE_DIGEST
|
||||||
|| BEGINS_WITH (au, "Digest")
|
|| BEGINS_WITH (au, "Digest")
|
||||||
|| BEGINS_WITH (au, "NTLM");
|
#endif
|
||||||
|
#ifdef ENABLE_NTLM
|
||||||
|
|| BEGINS_WITH (au, "NTLM")
|
||||||
|
#endif
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BEGINS_WITH
|
#undef BEGINS_WITH
|
||||||
@ -2855,10 +2827,20 @@ create_authorization_line (const char *au, const char *user,
|
|||||||
{
|
{
|
||||||
if (0 == strncasecmp (au, "Basic", 5))
|
if (0 == strncasecmp (au, "Basic", 5))
|
||||||
return basic_authentication_encode (user, passwd);
|
return basic_authentication_encode (user, passwd);
|
||||||
#ifdef USE_DIGEST
|
#ifdef ENABLE_DIGEST
|
||||||
if (0 == strncasecmp (au, "Digest", 6))
|
if (0 == strncasecmp (au, "Digest", 6))
|
||||||
return digest_authentication_encode (au, user, passwd, method, path);
|
return digest_authentication_encode (au, user, passwd, method, path);
|
||||||
#endif /* USE_DIGEST */
|
#endif
|
||||||
|
#ifdef ENABLE_NTLM
|
||||||
|
if (0 == strncasecmp (au, "NTLM", 4))
|
||||||
|
{
|
||||||
|
int ok = ntlm_input (&pconn.ntlm, au);
|
||||||
|
if (!ok)
|
||||||
|
return NULL;
|
||||||
|
/* #### we shouldn't ignore the OK that ntlm_output returns. */
|
||||||
|
return ntlm_output (&pconn.ntlm, user, passwd, &ok);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ fake_fork (void)
|
|||||||
|
|
||||||
/* Create the child process detached form the current console and in a
|
/* Create the child process detached form the current console and in a
|
||||||
suspended state. */
|
suspended state. */
|
||||||
memset (&si, 0, sizeof (si));
|
xzero (si);
|
||||||
si.cb = sizeof (si);
|
si.cb = sizeof (si);
|
||||||
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
|
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
|
||||||
CREATE_SUSPENDED | DETACHED_PROCESS,
|
CREATE_SUSPENDED | DETACHED_PROCESS,
|
||||||
|
140
src/utils.c
140
src/utils.c
@ -2170,3 +2170,143 @@ xsleep (double seconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* not WINDOWS */
|
#endif /* not WINDOWS */
|
||||||
|
|
||||||
|
/* Encode the string S of length LENGTH to base64 format and place it
|
||||||
|
to STORE. STORE will be 0-terminated, and must point to a writable
|
||||||
|
buffer of at least 1+BASE64_LENGTH(length) bytes. */
|
||||||
|
|
||||||
|
void
|
||||||
|
base64_encode (const char *s, char *store, int length)
|
||||||
|
{
|
||||||
|
/* Conversion table. */
|
||||||
|
static char tbl[64] = {
|
||||||
|
'A','B','C','D','E','F','G','H',
|
||||||
|
'I','J','K','L','M','N','O','P',
|
||||||
|
'Q','R','S','T','U','V','W','X',
|
||||||
|
'Y','Z','a','b','c','d','e','f',
|
||||||
|
'g','h','i','j','k','l','m','n',
|
||||||
|
'o','p','q','r','s','t','u','v',
|
||||||
|
'w','x','y','z','0','1','2','3',
|
||||||
|
'4','5','6','7','8','9','+','/'
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
unsigned char *p = (unsigned char *)store;
|
||||||
|
|
||||||
|
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
|
||||||
|
for (i = 0; i < length; i += 3)
|
||||||
|
{
|
||||||
|
*p++ = tbl[s[0] >> 2];
|
||||||
|
*p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
|
||||||
|
*p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
|
||||||
|
*p++ = tbl[s[2] & 0x3f];
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
/* Pad the result if necessary... */
|
||||||
|
if (i == length + 1)
|
||||||
|
*(p - 1) = '=';
|
||||||
|
else if (i == length + 2)
|
||||||
|
*(p - 1) = *(p - 2) = '=';
|
||||||
|
/* ...and zero-terminate it. */
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IS_ASCII(c) (((c) & 0x80) == 0)
|
||||||
|
#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
|
||||||
|
|
||||||
|
/* Get next character from the string, except that non-base64
|
||||||
|
characters are ignored, as mandated by rfc2045. */
|
||||||
|
#define NEXT_BASE64_CHAR(c, p) do { \
|
||||||
|
c = *p++; \
|
||||||
|
} while (c != '\0' && !IS_BASE64 (c))
|
||||||
|
|
||||||
|
/* Decode data from BASE64 (assumed to be encoded as base64) into
|
||||||
|
memory pointed to by TO. TO should be large enough to accomodate
|
||||||
|
the decoded data, which is guaranteed to be less than
|
||||||
|
strlen(base64).
|
||||||
|
|
||||||
|
Since TO is assumed to contain binary data, it is not
|
||||||
|
NUL-terminated. The function returns the length of the data
|
||||||
|
written to TO. -1 is returned in case of error caused by malformed
|
||||||
|
base64 input. */
|
||||||
|
|
||||||
|
int
|
||||||
|
base64_decode (const char *base64, char *to)
|
||||||
|
{
|
||||||
|
/* Table of base64 values for first 128 characters. */
|
||||||
|
static short base64_char_to_value[128] =
|
||||||
|
{
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
|
||||||
|
-1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
|
||||||
|
54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
|
||||||
|
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
|
||||||
|
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
|
||||||
|
25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
|
||||||
|
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
|
||||||
|
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
|
||||||
|
49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *p = base64;
|
||||||
|
char *q = to;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
unsigned char c;
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
/* Process first byte of a quadruplet. */
|
||||||
|
NEXT_BASE64_CHAR (c, p);
|
||||||
|
if (!c)
|
||||||
|
break;
|
||||||
|
if (c == '=')
|
||||||
|
return -1; /* illegal '=' while decoding base64 */
|
||||||
|
value = base64_char_to_value[c] << 18;
|
||||||
|
|
||||||
|
/* Process scond byte of a quadruplet. */
|
||||||
|
NEXT_BASE64_CHAR (c, p);
|
||||||
|
if (!c)
|
||||||
|
return -1; /* premature EOF while decoding base64 */
|
||||||
|
if (c == '=')
|
||||||
|
return -1; /* illegal `=' while decoding base64 */
|
||||||
|
value |= base64_char_to_value[c] << 12;
|
||||||
|
*q++ = value >> 16;
|
||||||
|
|
||||||
|
/* Process third byte of a quadruplet. */
|
||||||
|
NEXT_BASE64_CHAR (c, p);
|
||||||
|
if (!c)
|
||||||
|
return -1; /* premature EOF while decoding base64 */
|
||||||
|
|
||||||
|
if (c == '=')
|
||||||
|
{
|
||||||
|
NEXT_BASE64_CHAR (c, p);
|
||||||
|
if (!c)
|
||||||
|
return -1; /* premature EOF while dcoding base64 */
|
||||||
|
if (c != '=')
|
||||||
|
return -1; /* padding `=' expected but not found */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
value |= base64_char_to_value[c] << 6;
|
||||||
|
*q++ = 0xff & value >> 8;
|
||||||
|
|
||||||
|
/* Process fourth byte of a quadruplet. */
|
||||||
|
NEXT_BASE64_CHAR (c, p);
|
||||||
|
if (!c)
|
||||||
|
return -1; /* premature EOF while dcoding base64 */
|
||||||
|
if (c == '=')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
value |= base64_char_to_value[c];
|
||||||
|
*q++ = 0xff & value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return q - to;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef IS_ASCII
|
||||||
|
#undef IS_BASE64
|
||||||
|
#undef NEXT_BASE64_CHAR
|
||||||
|
@ -125,4 +125,10 @@ double random_float PARAMS ((void));
|
|||||||
int run_with_timeout PARAMS ((double, void (*) (void *), void *));
|
int run_with_timeout PARAMS ((double, void (*) (void *), void *));
|
||||||
void xsleep PARAMS ((double));
|
void xsleep PARAMS ((double));
|
||||||
|
|
||||||
|
/* How many bytes it will take to store LEN bytes in base64. */
|
||||||
|
#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))
|
||||||
|
|
||||||
|
void base64_encode PARAMS ((const char *, char *, int));
|
||||||
|
int base64_decode PARAMS ((const char *, char *));
|
||||||
|
|
||||||
#endif /* UTILS_H */
|
#endif /* UTILS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user