Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F20320739
t-http.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
12 KB
Subscribers
None
t-http.c
View Options
/* t-http.c
* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
* 2011 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - 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.
*
* or both in parallel, as here.
*
* This file 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 this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
<assuan.h>
#include
"../common/util.h"
#include
"../common/logging.h"
#include
"dns-stuff.h"
#include
"http.h"
#include
<ksba.h>
#if HTTP_USE_NTBTLS
# include <ntbtls.h>
#elif HTTP_USE_GNUTLS
# include <gnutls/gnutls.h>
/* For init, logging, and deinit. */
#endif
/*HTTP_USE_GNUTLS*/
#define PGM "t-http"
static
int
verbose
;
static
int
debug
;
static
int
no_verify
;
/* static void */
/* read_dh_params (const char *fname) */
/* { */
/* gpg_error_t err; */
/* int rc; */
/* FILE *fp; */
/* struct stat st; */
/* char *buf; */
/* size_t buflen; */
/* gnutls_datum_t datum; */
/* fp = fopen (fname, "rb"); */
/* if (!fp) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* if (fstat (fileno(fp), &st)) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* buflen = st.st_size; */
/* buf = xmalloc (buflen+1); */
/* if (fread (buf, buflen, 1, fp) != 1) */
/* { */
/* err = gpg_error_from_syserror (); */
/* log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */
/* } */
/* fclose (fp); */
/* datum.size = buflen; */
/* datum.data = buf; */
/* rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */
/* if (rc < 0) */
/* log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */
/* xfree (buf); */
/* } */
#if HTTP_USE_GNUTLS
static
gpg_error_t
verify_callback
(
http_t
hd
,
http_session_t
session
,
int
reserved
)
{
(
void
)
hd
;
(
void
)
reserved
;
return
no_verify
?
0
:
http_verify_server_credentials
(
session
);
}
#endif
#if HTTP_USE_GNUTLS
static
void
my_gnutls_log
(
int
level
,
const
char
*
text
)
{
fprintf
(
stderr
,
"gnutls:L%d: %s"
,
level
,
text
);
}
#endif
#if HTTP_USE_NTBTLS
static
gpg_error_t
my_http_tls_verify_cb
(
void
*
opaque
,
http_t
http
,
http_session_t
session
,
unsigned
int
http_flags
,
void
*
tls_context
)
{
gpg_error_t
err
;
int
idx
;
ksba_cert_t
cert
;
ksba_cert_t
hostcert
=
NULL
;
(
void
)
opaque
;
(
void
)
http
;
(
void
)
session
;
(
void
)
http_flags
;
/* Get the peer's certs fron ntbtls. */
for
(
idx
=
0
;
(
cert
=
ntbtls_x509_get_peer_cert
(
tls_context
,
idx
));
idx
++
)
{
if
(
!
idx
)
{
log_info
(
"Received host certificate
\n
"
);
hostcert
=
cert
;
}
else
{
log_info
(
"Received additional certificate
\n
"
);
ksba_cert_release
(
cert
);
}
}
if
(
!
idx
)
{
err
=
gpg_error
(
GPG_ERR_MISSING_CERT
);
goto
leave
;
}
err
=
0
;
leave
:
ksba_cert_release
(
hostcert
);
log_info
(
"my_http_tls_verify_cb returns: %s
\n
"
,
gpg_strerror
(
err
));
return
err
;
}
#endif
/*HTTP_USE_NTBTLS*/
/* Prepend FNAME with the srcdir environment variable's value and
return an allocated filename. */
static
char
*
prepend_srcdir
(
const
char
*
fname
)
{
static
const
char
*
srcdir
;
char
*
result
;
if
(
!
srcdir
&&
!
(
srcdir
=
getenv
(
"srcdir"
)))
srcdir
=
"."
;
result
=
xmalloc
(
strlen
(
srcdir
)
+
1
+
strlen
(
fname
)
+
1
);
strcpy
(
result
,
srcdir
);
strcat
(
result
,
"/"
);
strcat
(
result
,
fname
);
return
result
;
}
int
main
(
int
argc
,
char
**
argv
)
{
int
last_argc
=
-1
;
gpg_error_t
err
;
int
rc
;
parsed_uri_t
uri
;
uri_tuple_t
r
;
http_t
hd
;
int
c
;
unsigned
int
my_http_flags
=
0
;
int
no_out
=
0
;
int
tls_dbg
=
0
;
int
no_crl
=
0
;
const
char
*
cafile
=
NULL
;
http_session_t
session
=
NULL
;
unsigned
int
timeout
=
0
;
gpgrt_init
();
log_set_prefix
(
PGM
,
GPGRT_LOG_WITH_PREFIX
|
GPGRT_LOG_WITH_PID
);
if
(
argc
)
{
argc
--
;
argv
++
;
}
while
(
argc
&&
last_argc
!=
argc
)
{
last_argc
=
argc
;
if
(
!
strcmp
(
*
argv
,
"--"
))
{
argc
--
;
argv
++
;
break
;
}
else
if
(
!
strcmp
(
*
argv
,
"--help"
))
{
fputs
(
"usage: "
PGM
" URL
\n
"
"Options:
\n
"
" --verbose print timings etc.
\n
"
" --debug flyswatter
\n
"
" --tls-debug N use TLS debug level N
\n
"
" --cacert FNAME expect CA certificate in file FNAME
\n
"
" --timeout MS timeout for connect in MS
\n
"
" --no-verify do not verify the certificate
\n
"
" --force-tls use HTTP_FLAG_FORCE_TLS
\n
"
" --force-tor use HTTP_FLAG_FORCE_TOR
\n
"
" --no-out do not print the content
\n
"
" --no-crl do not consuilt a CRL
\n
"
,
stdout
);
exit
(
0
);
}
else
if
(
!
strcmp
(
*
argv
,
"--verbose"
))
{
verbose
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--debug"
))
{
verbose
+=
2
;
debug
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--tls-debug"
))
{
argc
--
;
argv
++
;
if
(
argc
)
{
tls_dbg
=
atoi
(
*
argv
);
argc
--
;
argv
++
;
}
}
else
if
(
!
strcmp
(
*
argv
,
"--cacert"
))
{
argc
--
;
argv
++
;
if
(
argc
)
{
cafile
=
*
argv
;
argc
--
;
argv
++
;
}
}
else
if
(
!
strcmp
(
*
argv
,
"--timeout"
))
{
argc
--
;
argv
++
;
if
(
argc
)
{
timeout
=
strtoul
(
*
argv
,
NULL
,
10
);
argc
--
;
argv
++
;
}
}
else
if
(
!
strcmp
(
*
argv
,
"--no-verify"
))
{
no_verify
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--force-tls"
))
{
my_http_flags
|=
HTTP_FLAG_FORCE_TLS
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--force-tor"
))
{
my_http_flags
|=
HTTP_FLAG_FORCE_TOR
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--no-out"
))
{
no_out
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--no-crl"
))
{
no_crl
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strncmp
(
*
argv
,
"--"
,
2
))
{
fprintf
(
stderr
,
PGM
": unknown option '%s'
\n
"
,
*
argv
);
exit
(
1
);
}
}
if
(
argc
!=
1
)
{
fprintf
(
stderr
,
PGM
": no or too many URLS given
\n
"
);
exit
(
1
);
}
if
(
!
cafile
)
cafile
=
prepend_srcdir
(
"tls-ca.pem"
);
if
(
verbose
)
my_http_flags
|=
HTTP_FLAG_LOG_RESP
;
if
(
verbose
||
debug
)
http_set_verbose
(
verbose
,
debug
);
/* http.c makes use of the assuan socket wrapper. */
assuan_sock_init
();
if
((
my_http_flags
&
HTTP_FLAG_FORCE_TOR
))
{
enable_dns_tormode
(
1
);
if
(
assuan_sock_set_flag
(
ASSUAN_INVALID_FD
,
"tor-mode"
,
1
))
{
log_error
(
"error enabling Tor mode: %s
\n
"
,
strerror
(
errno
));
log_info
(
"(is your Libassuan recent enough?)
\n
"
);
}
}
#if HTTP_USE_NTBTLS
log_info
(
"new session.
\n
"
);
err
=
http_session_new
(
&
session
,
NULL
,
((
no_crl
?
HTTP_FLAG_NO_CRL
:
0
)
|
HTTP_FLAG_TRUST_DEF
),
my_http_tls_verify_cb
,
NULL
);
if
(
err
)
log_error
(
"http_session_new failed: %s
\n
"
,
gpg_strerror
(
err
));
ntbtls_set_debug
(
tls_dbg
,
NULL
,
NULL
);
#elif HTTP_USE_GNUTLS
rc
=
gnutls_global_init
();
if
(
rc
)
log_error
(
"gnutls_global_init failed: %s
\n
"
,
gnutls_strerror
(
rc
));
http_register_tls_callback
(
verify_callback
);
http_register_tls_ca
(
cafile
);
err
=
http_session_new
(
&
session
,
NULL
,
((
no_crl
?
HTTP_FLAG_NO_CRL
:
0
)
|
HTTP_FLAG_TRUST_DEF
),
NULL
,
NULL
);
if
(
err
)
log_error
(
"http_session_new failed: %s
\n
"
,
gpg_strerror
(
err
));
/* rc = gnutls_dh_params_init(&dh_params); */
/* if (rc) */
/* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */
/* read_dh_params ("dh_param.pem"); */
/* rc = gnutls_certificate_set_x509_trust_file */
/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */
/* if (rc) */
/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */
/* gnutls_strerror (rc)); */
/* gnutls_certificate_set_dh_params (certcred, dh_params); */
gnutls_global_set_log_function
(
my_gnutls_log
);
if
(
tls_dbg
)
gnutls_global_set_log_level
(
tls_dbg
);
#else
(
void
)
err
;
(
void
)
tls_dbg
;
(
void
)
no_crl
;
#endif
/*HTTP_USE_GNUTLS*/
rc
=
http_parse_uri
(
&
uri
,
*
argv
,
1
);
if
(
rc
)
{
log_error
(
"'%s': %s
\n
"
,
*
argv
,
gpg_strerror
(
rc
));
return
1
;
}
printf
(
"Scheme: %s
\n
"
,
uri
->
scheme
);
if
(
uri
->
opaque
)
printf
(
"Value : %s
\n
"
,
uri
->
path
);
else
{
printf
(
"Auth : %s
\n
"
,
uri
->
auth
?
uri
->
auth
:
"[none]"
);
printf
(
"Host : %s
\n
"
,
uri
->
host
);
printf
(
"Port : %u
\n
"
,
uri
->
port
);
printf
(
"Path : %s
\n
"
,
uri
->
path
);
for
(
r
=
uri
->
params
;
r
;
r
=
r
->
next
)
{
printf
(
"Params: %s"
,
r
->
name
);
if
(
!
r
->
no_value
)
{
printf
(
"=%s"
,
r
->
value
);
if
(
strlen
(
r
->
value
)
!=
r
->
valuelen
)
printf
(
" [real length=%d]"
,
(
int
)
r
->
valuelen
);
}
putchar
(
'\n'
);
}
for
(
r
=
uri
->
query
;
r
;
r
=
r
->
next
)
{
printf
(
"Query : %s"
,
r
->
name
);
if
(
!
r
->
no_value
)
{
printf
(
"=%s"
,
r
->
value
);
if
(
strlen
(
r
->
value
)
!=
r
->
valuelen
)
printf
(
" [real length=%d]"
,
(
int
)
r
->
valuelen
);
}
putchar
(
'\n'
);
}
printf
(
"Flags :%s%s%s%s
\n
"
,
uri
->
is_http
?
" http"
:
""
,
uri
->
opaque
?
" opaque"
:
""
,
uri
->
v6lit
?
" v6lit"
:
""
,
uri
->
onion
?
" onion"
:
""
);
printf
(
"TLS : %s
\n
"
,
uri
->
use_tls
?
"yes"
:
(
my_http_flags
&
HTTP_FLAG_FORCE_TLS
)
?
"forced"
:
"no"
);
printf
(
"Tor : %s
\n
"
,
(
my_http_flags
&
HTTP_FLAG_FORCE_TOR
)
?
"yes"
:
"no"
);
}
fflush
(
stdout
);
http_release_parsed_uri
(
uri
);
uri
=
NULL
;
if
(
session
)
http_session_set_timeout
(
session
,
timeout
);
rc
=
http_open_document
(
&
hd
,
*
argv
,
NULL
,
my_http_flags
,
NULL
,
session
,
NULL
,
NULL
);
if
(
rc
)
{
log_error
(
"can't get '%s': %s
\n
"
,
*
argv
,
gpg_strerror
(
rc
));
return
1
;
}
log_info
(
"open_http_document succeeded; status=%u
\n
"
,
http_get_status_code
(
hd
));
{
const
char
**
names
;
int
i
;
names
=
http_get_header_names
(
hd
);
if
(
!
names
)
log_fatal
(
"http_get_header_names failed: %s
\n
"
,
gpg_strerror
(
gpg_error_from_syserror
()));
for
(
i
=
0
;
names
[
i
];
i
++
)
printf
(
"HDR: %s: %s
\n
"
,
names
[
i
],
http_get_header
(
hd
,
names
[
i
]));
xfree
(
names
);
}
fflush
(
stdout
);
switch
(
http_get_status_code
(
hd
))
{
case
200
:
case
400
:
case
401
:
case
403
:
case
404
:
{
unsigned
long
count
=
0
;
while
((
c
=
es_getc
(
http_get_read_ptr
(
hd
)))
!=
EOF
)
{
count
++
;
if
(
!
no_out
)
putchar
(
c
);
}
log_info
(
"Received bytes: %lu
\n
"
,
count
);
}
break
;
case
301
:
case
302
:
case
307
:
log_info
(
"Redirected to: %s
\n
"
,
http_get_header
(
hd
,
"Location"
));
break
;
}
http_close
(
hd
,
0
);
http_session_release
(
session
);
#ifdef HTTP_USE_GNUTLS
gnutls_global_deinit
();
#endif
/*HTTP_USE_GNUTLS*/
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Mar 14, 4:31 AM (1 d, 11 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a6/c0/ddb7d9174ff1ae862313d5dd33ec
Attached To
rG GnuPG
Event Timeline
Log In to Comment