aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/c_src/asn1_erl_driver.c3
-rw-r--r--lib/common_test/test/Makefile2
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c4
-rw-r--r--lib/erl_interface/src/prog/erl_call.c134
-rw-r--r--lib/et/test/Makefile3
-rw-r--r--lib/kernel/src/gen_sctp.erl30
-rw-r--r--lib/kernel/src/gen_tcp.erl36
-rw-r--r--lib/kernel/src/gen_udp.erl34
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl59
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl57
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl60
-rw-r--r--lib/mnesia/test/Makefile2
-rw-r--r--lib/public_key/include/public_key.hrl11
-rw-r--r--lib/public_key/src/pubkey_cert.erl349
-rw-r--r--lib/public_key/src/public_key.erl127
-rw-r--r--lib/public_key/test/public_key_SUITE.erl35
-rw-r--r--lib/reltool/test/Makefile3
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c2
-rw-r--r--lib/ssl/src/ssl.erl82
-rw-r--r--lib/ssl/src/ssl_certificate.erl39
-rw-r--r--lib/ssl/src/ssl_connection.erl13
-rw-r--r--lib/ssl/src/ssl_handshake.erl131
-rw-r--r--lib/ssl/src/ssl_internal.hrl1
-rw-r--r--lib/ssl/src/ssl_session.erl4
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl164
-rw-r--r--lib/stdlib/doc/src/erl_id_trans.xml5
-rw-r--r--lib/stdlib/doc/src/erl_lint.xml4
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml2
-rw-r--r--lib/stdlib/doc/src/lists.xml6
-rw-r--r--lib/stdlib/doc/src/sys.xml2
-rw-r--r--lib/test_server/src/Makefile2
-rw-r--r--lib/test_server/test/Makefile2
-rw-r--r--lib/tools/doc/src/erlang_mode.xml2
-rw-r--r--lib/tools/doc/src/erlang_mode_chapter.xml2
-rw-r--r--lib/wx/test/Makefile2
-rw-r--r--lib/xmerl/src/xmerl_scan.erl33
36 files changed, 881 insertions, 566 deletions
diff --git a/lib/asn1/c_src/asn1_erl_driver.c b/lib/asn1/c_src/asn1_erl_driver.c
index fd284e5800..9dd3a0fd7d 100644
--- a/lib/asn1/c_src/asn1_erl_driver.c
+++ b/lib/asn1/c_src/asn1_erl_driver.c
@@ -1407,7 +1407,6 @@ int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_l
int msg_index_val;
int *msg_index, *tag_index, tmp_index;
int tag_seq_length;
- char tag_code; /* one of ASN1_SKIPPED, ASN1_OPTIONAL, ASN1_CHOOSEN */
int wanted_tag, next_tag;
int buf_end_index = in_buf_len;
int ret = 0, length, old_index;
@@ -1600,7 +1599,7 @@ int get_value(char *out_buf,
{
int len, lenoflen, indef=0, skip_len;
int ret=0;
- int start_index, out_index = 0;
+ int start_index;
/* printf("get_value 1\n\r"); */
if (in_buf[*msg_index] < 0x80){ /* short definite length */
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 3fb0d627a0..e3dc78ed75 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -92,7 +92,7 @@ release_spec: opt
release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_PROGRAM) common_test.spec $(RELSYSDIR)
+ $(INSTALL_DATA) common_test.spec $(RELSYSDIR)
chmod -f -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 42aeab22b1..24a030c468 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -601,7 +601,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000))
+#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
struct hostent *result;
gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result,
@@ -628,7 +628,7 @@ struct hostent *ei_gethostbyname_r(const char *name,
#ifndef HAVE_GETHOSTBYNAME_R
return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop);
#else
-#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000))
+#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__))
struct hostent *result;
gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop);
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 93b84cbb36..448de9aa23 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -123,6 +123,10 @@ static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);
static int read_stdin(char **buf);
static void split_apply_string(char *str, char **mod,
char **fun, char **args);
+static void* ei_chk_malloc(size_t size);
+static void* ei_chk_calloc(size_t nmemb, size_t size);
+static void* ei_chk_realloc(void *old, size_t size);
+static char* ei_chk_strdup(char *s);
/***************************************************************************
@@ -132,7 +136,6 @@ static void split_apply_string(char *str, char **mod,
***************************************************************************/
/* FIXME isn't VxWorks to handle arguments differently? */
-/* FIXME check errors from malloc */
#if !defined(VXWORKS)
int main(int argc, char *argv[])
@@ -165,8 +168,7 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-sname ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
i++;
flags.use_long_name = 0;
} else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
@@ -174,8 +176,7 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-name ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
i++;
flags.use_long_name = 1;
} else {
@@ -210,16 +211,14 @@ int erl_call(int argc, char **argv)
usage_arg(progname, "-c ");
}
flags.cookiep = 1;
- flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.cookie, argv[i+1]);
+ flags.cookie = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'n':
if (i+1 >= argc) {
usage_arg(progname, "-n ");
}
- flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.node, argv[i+1]);
+ flags.node = ei_chk_strdup(argv[i+1]);
flags.use_long_name = 1;
i++;
break;
@@ -227,24 +226,21 @@ int erl_call(int argc, char **argv)
if (i+1 >= argc) {
usage_arg(progname, "-h ");
}
- flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.hidden, argv[i+1]);
+ flags.hidden = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'x':
if (i+1 >= argc) {
usage_arg(progname, "-x ");
}
- flags.script = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.script, argv[i+1]);
+ flags.script = ei_chk_strdup(argv[i+1]);
i++;
break;
case 'a':
if (i+1 >= argc) {
usage_arg(progname, "-a ");
}
- flags.apply = (char *) malloc(strlen(argv[i+1]) + 1);
- strcpy(flags.apply, argv[i+1]);
+ flags.apply = ei_chk_strdup(argv[i+1]);
i++;
break;
case '?':
@@ -304,8 +300,7 @@ int erl_call(int argc, char **argv)
if (flags.hidden == NULL) {
/* As default we are c17@gethostname */
i = flags.randomp ? (time(NULL) % 997) : 17;
- /* FIXME allocates to small !!! */
- flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */
+ flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */
#if defined(VXWORKS)
sprintf(flags.hidden, "c%d",
i < 0 ? (int) taskIdSelf() : i);
@@ -330,17 +325,25 @@ int erl_call(int argc, char **argv)
initWinSock();
#endif
- gethostname(h_hostname, EI_MAXHOSTNAMELEN);
+ if (gethostname(h_hostname, EI_MAXHOSTNAMELEN) < 0) {
+ fprintf(stderr,"erl_call: failed to get host name: %d\n", errno);
+ exit(1);
+ }
if ((hp = ei_gethostbyname(h_hostname)) == 0) {
fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname);
exit(1);
}
- /* If shortnames cut of the name at first '.' */
+ /* If shortnames, cut off the name at first '.' */
if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
*ct = '\0';
}
- strcpy(h_hostname, hp->h_name);
+ strncpy(h_hostname, hp->h_name, EI_MAXHOSTNAMELEN);
+ h_hostname[EI_MAXHOSTNAMELEN] = '\0';
memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
+ if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename)) {
+ fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname);
+ exit(1);
+ }
sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);
if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename,
@@ -368,11 +371,16 @@ int erl_call(int argc, char **argv)
fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host);
exit(1);
}
- /* If shortnames cut of the name at first '.' */
+ /* If shortnames, cut off the name at first '.' */
if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
*ct = '\0';
}
- strcpy(host_name, hp->h_name);
+ strncpy(host_name, hp->h_name, EI_MAXHOSTNAMELEN);
+ host_name[EI_MAXHOSTNAMELEN] = '\0';
+ if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) {
+ fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node);
+ exit(1);
+ }
sprintf(nodename, "%s@%s", flags.node, host_name);
/*
@@ -401,7 +409,7 @@ int erl_call(int argc, char **argv)
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_empty_list(p, &i);
@@ -426,6 +434,10 @@ int erl_call(int argc, char **argv)
if (flags.modp && (modname != NULL)) {
char fname[256];
+ if (strlen(modname) + 4 + 1 > sizeof(fname)) {
+ fprintf(stderr,"erl_call: module name too long: %s\n", modname);
+ exit(1);
+ }
strcpy(fname, modname);
strcat(fname, ".erl");
@@ -443,7 +455,7 @@ int erl_call(int argc, char **argv)
ei_encode_binary(NULL, &i, module, modsize);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 2);
@@ -476,7 +488,7 @@ int erl_call(int argc, char **argv)
ei_encode_empty_list(NULL, &i);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 2);
@@ -521,7 +533,7 @@ int erl_call(int argc, char **argv)
ei_encode_binary(NULL, &i, evalbuf, len);
ei_encode_empty_list(NULL, &i);
- p = (char *)malloc(i);
+ p = (char *)ei_chk_malloc(i);
i = 0; /* Reset */
ei_encode_list_header(p, &i, 1);
@@ -719,32 +731,28 @@ static void split_apply_string(char *str,
EAT(str);
len = str-begin;
- *mod = (char *) calloc(len + 1, sizeof(char));
+ *mod = (char *) ei_chk_calloc(len + 1, sizeof(char));
memcpy(*mod, begin, len);
SKIP_SPACE(str);
if (*str == '\0') {
- *fun = (char *) calloc(strlen(start)+1, sizeof(char));
- strcpy(*fun, start);
- *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
- strcpy(*args, empty_list);
+ *fun = ei_chk_strdup(start);
+ *args = ei_chk_strdup(empty_list);
return;
}
begin = str;
EAT(str);
len = str-begin;
- *fun = (char *) calloc(len + 1, sizeof(char));
+ *fun = (char *) ei_chk_calloc(len + 1, sizeof(char));
memcpy(*fun, begin, len);
SKIP_SPACE(str);
if (*str == '\0') {
- *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
- strcpy(*args, empty_list);
+ *args = ei_chk_strdup(empty_list);
return;
}
- *args = (char *) calloc(strlen(str) + 1, sizeof(char));
- strcpy(*args, str);
+ *args = ei_chk_strdup(str);
return;
@@ -760,7 +768,7 @@ static int read_stdin(char **buf)
int bsize = BUFSIZ;
int len = 0;
int i;
- char *tmp = (char *) malloc(bsize);
+ char *tmp = (char *) ei_chk_malloc(bsize);
while (1) {
if ((i = read(0, &tmp[len], bsize-len)) < 0) {
@@ -772,7 +780,7 @@ static int read_stdin(char **buf)
len += i;
if ((len+50) > bsize) {
bsize = len * 2;
- tmp = (char *) realloc(tmp, bsize);
+ tmp = (char *) ei_chk_realloc(tmp, bsize);
} else {
continue;
}
@@ -809,7 +817,7 @@ static int get_module(char **mbuf, char **mname)
}
} /* while */
i = tmp - start;
- *mname = (char *) calloc(i+1, sizeof(char));
+ *mname = (char *) ei_chk_calloc(i+1, sizeof(char));
memcpy(*mname, start, i);
}
if (*mbuf)
@@ -905,3 +913,51 @@ static void initWinSock(void)
}
}
#endif
+
+
+/***************************************************************************
+ *
+ * Utility functions
+ *
+ ***************************************************************************/
+
+static void* ei_chk_malloc(size_t size)
+{
+ void *p = malloc(size);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+static void* ei_chk_calloc(size_t nmemb, size_t size)
+{
+ void *p = calloc(nmemb, size);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+static void* ei_chk_realloc(void *old, size_t size)
+{
+ void *p = realloc(old, size);
+ if (!p) {
+ fprintf(stderr, "erl_call: cannot reallocate %u bytes of memory from %p\n",
+ (unsigned) size, old);
+ exit (1);
+ }
+ return p;
+}
+
+static char* ei_chk_strdup(char *s)
+{
+ char *p = strdup(s);
+ if (p == NULL) {
+ fprintf(stderr,"erl_call: insufficient memory\n");
+ exit(1);
+ }
+ return p;
+}
diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile
index 9aedf96ce9..7227ae8fd8 100644
--- a/lib/et/test/Makefile
+++ b/lib/et/test/Makefile
@@ -72,7 +72,8 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) et.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) ett $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) ett $(RELSYSDIR)
+ $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index a1542ab507..cccfa75005 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -39,7 +39,7 @@ open() ->
open([]).
open(Opts) when is_list(Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
case Mod:open(Opts) of
{error,badarg} ->
erlang:error(badarg, [Opts]);
@@ -234,17 +234,27 @@ controlling_process(S, Pid) ->
%% Utilites
%%
-%% Get the SCTP moudule
-mod() -> inet_db:sctp_module().
+%% Get the SCTP module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:sctp_module() of
+ inet_sctp when tuple_size(Address) =:= 8 ->
+ inet6_sctp;
+ Mod ->
+ Mod
+ end.
%% Get the SCTP module, but option sctp_module|inet|inet6 overrides
-mod([{sctp_module,Mod}|_]) ->
+mod([{sctp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_sctp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_sctp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 7401b06a64..16a87d71b6 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,7 +46,7 @@ connect(Address, Port, Opts, Time) ->
end.
connect1(Address,Port,Opts,Timer) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, Address),
case Mod:getaddrs(Address,Timer) of
{ok,IPs} ->
case Mod:getserv(Port) of
@@ -73,7 +73,7 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
%% Listen on a tcp port
%%
listen(Port, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
case Mod:getserv(Port) of
{ok,TP} ->
Mod:listen(TP, Opts);
@@ -173,20 +173,30 @@ controlling_process(S, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
Mod:fdopen(Fd, Opts).
-%% Get the tcp_module
-mod() -> inet_db:tcp_module().
+%% Get the tcp_module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:tcp_module() of
+ inet_tcp when tuple_size(Address) =:= 8 ->
+ inet6_tcp;
+ Mod ->
+ Mod
+ end.
%% Get the tcp_module, but option tcp_module|inet|inet6 overrides
-mod([{tcp_module,Mod}|_]) ->
+mod([{tcp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_tcp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_tcp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 6bded4bda6..99020c7b6c 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@ open(Port) ->
open(Port, []).
open(Port, Opts) ->
- Mod = mod(Opts),
+ Mod = mod(Opts, undefined),
{ok,UP} = Mod:getserv(Port),
Mod:open(UP, Opts).
@@ -97,21 +97,31 @@ controlling_process(S, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- Mod = mod(),
+ Mod = mod(Opts, undefined),
Mod:fdopen(Fd, Opts).
-%% Get the udp_module
-mod() -> inet_db:udp_module().
+%% Get the udp_module, but IPv6 address overrides default IPv4
+mod(Address) ->
+ case inet_db:udp_module() of
+ inet_udp when tuple_size(Address) =:= 8 ->
+ inet6_udp;
+ Mod ->
+ Mod
+ end.
%% Get the udp_module, but option udp_module|inet|inet6 overrides
-mod([{udp_module,Mod}|_]) ->
+mod([{udp_module,Mod}|_], _Address) ->
Mod;
-mod([inet|_]) ->
+mod([inet|_], _Address) ->
inet_udp;
-mod([inet6|_]) ->
+mod([inet6|_], _Address) ->
inet6_udp;
-mod([_|Opts]) ->
- mod(Opts);
-mod([]) ->
- mod().
+mod([{ip, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([{ifaddr, Address}|Opts], _) ->
+ mod(Opts, Address);
+mod([_|Opts], Address) ->
+ mod(Opts, Address);
+mod([], Address) ->
+ mod(Address).
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index eb06d4324b..9aa94a0868 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -27,12 +27,12 @@
-export(
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
- xfer_min/1,xfer_active/1,def_sndrcvinfo/1]).
+ xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]).
all(suite) ->
[basic,
api_open_close,api_listen,api_connect_init,api_opts,
- xfer_min,xfer_active,def_sndrcvinfo].
+ xfer_min,xfer_active,def_sndrcvinfo,implicit_inet6].
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(15)),
@@ -551,3 +551,58 @@ api_opts(Config) when is_list(Config) ->
{{error,einval},{unix,sunos}} ->
ok
end.
+
+implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line
+ case gen_sctp:open(0, [inet6]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Loopback),
+ ?line ok = gen_sctp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 =
+ ok(gen_sctp:open(0, [{ip,Localhost}])),
+ ?line implicit_inet6(S2, Localhost),
+ ?line ok = gen_sctp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 =
+ ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ ?line implicit_inet6(S3, Host),
+ ?line ok = gen_sctp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_sctp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S1, Addr) ->
+ ?line ok = gen_sctp:listen(S1, true),
+ ?line P1 = ok(inet:port(S1)),
+ ?line S2 = ok(gen_sctp:open(0, [inet6])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line #sctp_assoc_change{state=comm_up} =
+ ok(gen_sctp:connect(S2, Addr, P1, [])),
+ ?line case ok(gen_sctp:recv(S1)) of
+ {Addr,P2,[],#sctp_assoc_change{state=comm_up}} ->
+ ok
+ end,
+ ?line case ok(inet:sockname(S1)) of
+ {Addr,P1} -> ok;
+ {{0,0,0,0,0,0,0,0},P1} -> ok
+ end,
+ ?line case ok(inet:sockname(S2)) of
+ {Addr,P2} -> ok;
+ {{0,0,0,0,0,0,0,0},P2} -> ok
+ end,
+ ?line ok = gen_sctp:close(S2).
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 11d19aaa82..94637290a1 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,10 +30,11 @@
t_connect/1, t_connect_bad/1,
t_recv/1, t_recv_timeout/1, t_recv_eof/1,
t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1,
- t_fdopen/1]).
+ t_fdopen/1, t_implicit_inet6/1]).
all(suite) -> [t_accept, t_connect, t_recv, t_shutdown_write,
- t_shutdown_both, t_shutdown_error, t_fdopen].
+ t_shutdown_both, t_shutdown_error, t_fdopen,
+ t_implicit_inet6].
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -156,6 +157,54 @@ t_fdopen(Config) when is_list(Config) ->
ok.
+%%% implicit inet6 option to api functions
+
+t_implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line
+ case gen_tcp:listen(0, [inet6]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Loopback),
+ ?line ok = gen_tcp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 = ok(gen_tcp:listen(0, [{ip,Localhost}])),
+ ?line implicit_inet6(S2, Localhost),
+ ?line ok = gen_tcp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 = ok(gen_tcp:listen(0, [{ifaddr,Host}])),
+ ?line implicit_inet6(S3, Host),
+ ?line ok = gen_tcp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_tcp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S, Addr) ->
+ ?line P = ok(inet:port(S)),
+ ?line S2 = ok(gen_tcp:connect(Addr, P, [])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line S1 = ok(gen_tcp:accept(S)),
+ ?line P1 = P = ok(inet:port(S1)),
+ ?line {Addr,P2} = ok(inet:peername(S1)),
+ ?line {Addr,P1} = ok(inet:peername(S2)),
+ ?line {Addr,P1} = ok(inet:sockname(S1)),
+ ?line {Addr,P2} = ok(inet:sockname(S2)),
+ ?line ok = gen_tcp:close(S2),
+ ?line ok = gen_tcp:close(S1).
+
+
%%% Utilities
@@ -217,3 +266,5 @@ unused_ip(A, B, C, D) ->
{ok, _} -> unused_ip(A, B, C, D+1);
{error, _} -> {ok, {A, B, C, D}}
end.
+
+ok({ok,V}) -> V.
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index fa1991872b..44dd8607b9 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,12 +34,12 @@
-export([send_to_closed/1,
buffer_size/1, binary_passive_recv/1, bad_address/1,
- read_packets/1, open_fd/1, connect/1]).
+ read_packets/1, open_fd/1, connect/1, implicit_inet6/1]).
all(suite) ->
[send_to_closed,
buffer_size, binary_passive_recv, bad_address, read_packets,
- open_fd, connect].
+ open_fd, connect, implicit_inet6].
init_per_testcase(_Case, Config) ->
?line Dog=test_server:timetrap(?default_timeout),
@@ -425,3 +425,57 @@ connect(Config) when is_list(Config) ->
ok = gen_udp:send(S2, <<16#deadbeef:32>>),
{error,econnrefused} = gen_udp:recv(S2, 0, 5),
ok.
+
+implicit_inet6(Config) when is_list(Config) ->
+ ?line Hostname = ok(inet:gethostname()),
+ ?line Active = {active,false},
+ ?line
+ case gen_udp:open(0, [inet6,Active]) of
+ {ok,S1} ->
+ ?line
+ case inet:getaddr(Hostname, inet6) of
+ {ok,Host} ->
+ ?line Loopback = {0,0,0,0,0,0,0,1},
+ ?line io:format("~s ~p~n", ["Loopback",Loopback]),
+ ?line implicit_inet6(S1, Active, Loopback),
+ ?line ok = gen_udp:close(S1),
+ %%
+ ?line Localhost =
+ ok(inet:getaddr("localhost", inet6)),
+ ?line io:format("~s ~p~n", ["localhost",Localhost]),
+ ?line S2 =
+ ok(gen_udp:open(0, [{ip,Localhost},Active])),
+ ?line implicit_inet6(S2, Active, Localhost),
+ ?line ok = gen_udp:close(S2),
+ %%
+ ?line io:format("~s ~p~n", [Hostname,Host]),
+ ?line S3 =
+ ok(gen_udp:open(0, [{ifaddr,Host},Active])),
+ ?line implicit_inet6(S3, Active, Host),
+ ?line ok = gen_udp:close(S1);
+ {error,eafnosupport} ->
+ ?line ok = gen_udp:close(S1),
+ {skip,"Can not look up IPv6 address"}
+ end;
+ _ ->
+ {skip,"IPv6 not supported"}
+ end.
+
+implicit_inet6(S1, Active, Addr) ->
+ ?line P1 = ok(inet:port(S1)),
+ ?line S2 = ok(gen_udp:open(0, [inet6,Active])),
+ ?line P2 = ok(inet:port(S2)),
+ ?line ok = gen_udp:connect(S2, Addr, P1),
+ ?line ok = gen_udp:connect(S1, Addr, P2),
+ ?line {Addr,P2} = ok(inet:peername(S1)),
+ ?line {Addr,P1} = ok(inet:peername(S2)),
+ ?line {Addr,P1} = ok(inet:sockname(S1)),
+ ?line {Addr,P2} = ok(inet:sockname(S2)),
+ ?line ok = gen_udp:send(S1, Addr, P2, "ping"),
+ ?line {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
+ ?line ok = gen_udp:send(S2, Addr, P1, "pong"),
+ ?line {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
+ ?line ok = gen_udp:close(S2).
+
+
+ok({ok,V}) -> V.
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile
index a4f32e3f78..4f98efaed1 100644
--- a/lib/mnesia/test/Makefile
+++ b/lib/mnesia/test/Makefile
@@ -109,7 +109,7 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) mnesia.spec mnesia.spec.vxworks $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) mt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) mt $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 6503321042..82681502ab 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,6 +28,13 @@
algorithm,
parameters = asn1_NOVALUE}).
+-define(DEFAULT_VERIFYFUN,
+ {fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []}).
+
-record(path_validation_state, {
valid_policy_tree,
explicit_policy,
@@ -42,7 +49,7 @@
working_public_key_parameters,
working_issuer_name,
max_path_length,
- acc_errors, %% If verify_none option is set
+ verify_fun,
user_state
}).
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 64fc8ab5bc..b3c230df25 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -27,7 +27,6 @@
validate_time/3, validate_signature/6,
validate_issuer/4, validate_names/6,
validate_revoked_status/3, validate_extensions/4,
- validate_unknown_extensions/3,
normalize_general_name/1, digest_type/1, is_self_signed/1,
is_issuer/2, issuer_id/2, is_fixed_dh_cert/1,
verify_data/1]).
@@ -68,13 +67,14 @@ init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen,
Options, false)),
PolicyMapping = policy_indicator(MaxLen,
proplists:get_value(policy_mapping, Options, false)),
- AccErrors = proplists:get_value(acc_errors, Options, []),
- State = #path_validation_state{max_path_length = MaxLen,
- valid_policy_tree = PolicyTree,
- explicit_policy = ExplicitPolicy,
- inhibit_any_policy = InhibitAnyPolicy,
- policy_mapping = PolicyMapping,
- acc_errors = AccErrors,
+ {VerifyFun, UserState} = proplists:get_value(verify_fun, Options, ?DEFAULT_VERIFYFUN),
+ State = #path_validation_state{max_path_length = MaxLen,
+ valid_policy_tree = PolicyTree,
+ explicit_policy = ExplicitPolicy,
+ inhibit_any_policy = InhibitAnyPolicy,
+ policy_mapping = PolicyMapping,
+ verify_fun = VerifyFun,
+ user_state = UserState,
cert_num = 0},
prepare_for_next_cert(OtpCert, State).
@@ -112,12 +112,12 @@ prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{
}.
%%--------------------------------------------------------------------
--spec validate_time(#'OTPCertificate'{}, list(), boolean()) -> list().
+-spec validate_time(#'OTPCertificate'{}, term(), fun()) -> term().
%%
%% Description: Check that the certificate validity period includes the
%% current time.
%%--------------------------------------------------------------------
-validate_time(OtpCert, AccErr, Verify) ->
+validate_time(OtpCert, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
{'Validity', NotBeforeStr, NotAfterStr}
= TBSCert#'OTPTBSCertificate'.validity,
@@ -127,27 +127,27 @@ validate_time(OtpCert, AccErr, Verify) ->
case ((NotBefore =< Now) and (Now =< NotAfter)) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, cert_expired}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, cert_expired}, UserState, VerifyFun)
end.
%%--------------------------------------------------------------------
--spec validate_issuer(#'OTPCertificate'{}, term(), list(), boolean()) -> list().
+-spec validate_issuer(#'OTPCertificate'{}, term(), term(), fun()) -> term().
%%
%% Description: Check that the certificate issuer name is the working_issuer_name
%% in path_validation_state.
%%--------------------------------------------------------------------
-validate_issuer(OtpCert, Issuer, AccErr, Verify) ->
+validate_issuer(OtpCert, Issuer, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
case is_issuer(Issuer, TBSCert#'OTPTBSCertificate'.issuer) of
true ->
- AccErr;
+ UserState;
_ ->
- not_valid({bad_cert, invalid_issuer}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, invalid_issuer}, UserState, VerifyFun)
end.
%%--------------------------------------------------------------------
-spec validate_signature(#'OTPCertificate'{}, der_encoded(),
- term(),term(), list(), boolean()) -> list().
+ term(),term(), term(), fun()) -> term().
%%
%% Description: Check that the signature on the certificate can be verified using
@@ -155,24 +155,24 @@ validate_issuer(OtpCert, Issuer, AccErr, Verify) ->
%% the working_public_key_parameters in path_validation_state.
%%--------------------------------------------------------------------
validate_signature(OtpCert, DerCert, Key, KeyParams,
- AccErr, Verify) ->
+ UserState, VerifyFun) ->
case verify_signature(OtpCert, DerCert, Key, KeyParams) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, invalid_signature}, Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, invalid_signature}, UserState, VerifyFun)
end.
%%--------------------------------------------------------------------
-spec validate_names(#'OTPCertificate'{}, list(), list(),
- term(), list(), boolean())-> list().
+ term(), term(), fun())-> term().
%%
%% Description: Validate Subject Alternative Name.
%%--------------------------------------------------------------------
-validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) ->
+validate_names(OtpCert, Permit, Exclude, Last, UserState, VerifyFun) ->
case is_self_signed(OtpCert) andalso (not Last) of
true ->
- AccErr;
+ UserState;
false ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
Subject = TBSCert#'OTPTBSCertificate'.subject,
@@ -196,51 +196,36 @@ validate_names(OtpCert, Permit, Exclude, Last, AccErr, Verify) ->
(not is_excluded(Name, Exclude)) andalso
(not is_excluded(AltNames, Exclude))) of
true ->
- AccErr;
+ UserState;
false ->
- not_valid({bad_cert, name_not_permitted},
- Verify, AccErr)
+ verify_fun(OtpCert, {bad_cert, name_not_permitted},
+ UserState, VerifyFun)
end
end.
%%--------------------------------------------------------------------
--spec validate_revoked_status(#'OTPCertificate'{}, boolean(), list()) ->
- list().
+-spec validate_revoked_status(#'OTPCertificate'{}, term(), fun()) ->
+ term().
%%
%% Description: Check if certificate has been revoked.
%%--------------------------------------------------------------------
-validate_revoked_status(_OtpCert, _Verify, AccErr) ->
+validate_revoked_status(_OtpCert, UserState, _VerifyFun) ->
%% TODO: Implement or leave for application?!
- %% true |
+ %% valid |
%% throw({bad_cert, cert_revoked})
- AccErr.
+ UserState.
%%--------------------------------------------------------------------
-spec validate_extensions(#'OTPCertificate'{}, #path_validation_state{},
- boolean(), list())->
- {#path_validation_state{},
- UnknownExtensions :: list(), AccErrors :: list()}.
+ term(), fun())->
+ {#path_validation_state{}, UserState :: term()}.
%%
%% Description: Check extensions included in basic path validation.
%%--------------------------------------------------------------------
-validate_extensions(OtpCert, ValidationState, Verify, AccErr) ->
+validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- validate_extensions(Extensions, ValidationState, no_basic_constraint,
- is_self_signed(OtpCert), [], Verify, AccErr).
-
-%--------------------------------------------------------------------
- -spec validate_unknown_extensions(list(), list(), boolean())-> list().
-%%
-%% Description: Check that all critical extensions has been handled.
-%%--------------------------------------------------------------------
-validate_unknown_extensions([], AccErr, _Verify) ->
- AccErr;
-validate_unknown_extensions([#'Extension'{critical = true} | _],
- AccErr, Verify) ->
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr);
-validate_unknown_extensions([#'Extension'{critical = false} | Rest],
- AccErr, Verify) ->
- validate_unknown_extensions(Rest, AccErr, Verify).
+ validate_extensions(OtpCert, Extensions, ValidationState, no_basic_constraint,
+ is_self_signed(OtpCert), UserState, VerifyFun).
%%--------------------------------------------------------------------
-spec normalize_general_name({rdnSequence, term()}) -> {rdnSequence, term()}.
@@ -330,10 +315,25 @@ extensions_list(asn1_NOVALUE) ->
extensions_list(Extensions) ->
Extensions.
-not_valid(Error, true, _) ->
- throw(Error);
-not_valid(Error, false, AccErrors) ->
- [Error | AccErrors].
+verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
+ case VerifyFun(Otpcert, Result, UserState0) of
+ {valid,UserState} ->
+ UserState;
+ {fail, Reason} ->
+ case Result of
+ {bad_cert, _} ->
+ throw(Result);
+ _ ->
+ throw({bad_cert, Reason})
+ end;
+ {unknown, UserState} ->
+ case Result of
+ {extension, #'Extension'{critical = true}} ->
+ throw({bad_cert, unknown_critical_extension});
+ _ ->
+ UserState
+ end
+ end.
extract_verify_data(OtpCert, DerCert) ->
{0, Signature} = OtpCert#'OTPCertificate'.signature,
@@ -460,198 +460,189 @@ select_extension(Id, [_ | Extensions]) ->
select_extension(Id, Extensions).
%% No extensions present
-validate_extensions(asn1_NOVALUE, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions([], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-validate_extensions([], ValidationState, basic_constraint, _SelfSigned,
- UnknownExtensions, _Verify, AccErr) ->
- {ValidationState, UnknownExtensions, AccErr};
-validate_extensions([], ValidationState =
- #path_validation_state{max_path_length = Len,
- last_cert = Last},
- no_basic_constraint, SelfSigned, UnknownExtensions,
- Verify, AccErr0) ->
+validate_extensions(OtpCert, asn1_NOVALUE, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
+ validate_extensions(OtpCert, [], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(_,[], ValidationState, basic_constraint, _SelfSigned,
+ UserState, _) ->
+ {ValidationState, UserState};
+validate_extensions(OtpCert, [], ValidationState =
+ #path_validation_state{max_path_length = Len,
+ last_cert = Last},
+ no_basic_constraint, SelfSigned, UserState0, VerifyFun) ->
case Last of
true when SelfSigned ->
- {ValidationState, UnknownExtensions, AccErr0};
+ {ValidationState, UserState0};
true ->
{ValidationState#path_validation_state{max_path_length = Len - 1},
- UnknownExtensions, AccErr0};
+ UserState0};
%% basic_constraint must appear in certs used for digital sign
%% see 4.2.1.10 in rfc 3280
false ->
- AccErr = not_valid({bad_cert, missing_basic_constraint},
- Verify, AccErr0),
+ UserState = verify_fun(OtpCert, {bad_cert, missing_basic_constraint},
+ UserState0, VerifyFun),
case SelfSigned of
true ->
- {ValidationState, UnknownExtensions, AccErr};
+ {ValidationState, UserState};
false ->
{ValidationState#path_validation_state{max_path_length =
- Len - 1},
- UnknownExtensions, AccErr}
+ Len - 1},
+ UserState}
end
end;
-validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints',
+validate_extensions(OtpCert,
+ [#'Extension'{extnID = ?'id-ce-basicConstraints',
extnValue =
- #'BasicConstraints'{cA = true,
- pathLenConstraint = N}} |
+ #'BasicConstraints'{cA = true,
+ pathLenConstraint = N}} |
Rest],
- ValidationState =
- #path_validation_state{max_path_length = Len}, _,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
+ ValidationState =
+ #path_validation_state{max_path_length = Len}, _,
+ SelfSigned, UserState, VerifyFun) ->
Length = if SelfSigned -> erlang:min(N, Len);
true -> erlang:min(N, Len-1)
end,
- validate_extensions(Rest,
+ validate_extensions(OtpCert, Rest,
ValidationState#path_validation_state{max_path_length =
- Length},
- basic_constraint, SelfSigned, UnknownExtensions,
- Verify, AccErr);
+ Length},
+ basic_constraint, SelfSigned,
+ UserState, VerifyFun);
%% The pathLenConstraint field is meaningful only if cA is set to
%% TRUE.
-validate_extensions([#'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue =
- #'BasicConstraints'{cA = false}} |
- Rest], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-%%
-validate_extensions([#'Extension'{extnID = ?'id-ce-keyUsage',
- extnValue = KeyUse
- } | Rest],
- #path_validation_state{last_cert=Last} = ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue =
+ #'BasicConstraints'{cA = false}} |
+ Rest], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = KeyUse
+ } | Rest],
+ #path_validation_state{last_cert=Last} = ValidationState,
+ ExistBasicCon, SelfSigned,
+ UserState0, VerifyFun) ->
case Last orelse is_valid_key_usage(KeyUse, keyCertSign) of
true ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr0);
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun);
false ->
- AccErr = not_valid({bad_cert, invalid_key_usage}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr)
+ UserState = verify_fun(OtpCert, {bad_cert, invalid_key_usage},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun)
end;
-validate_extensions([#'Extension'{extnID = ?'id-ce-subjectAltName',
- extnValue = Names} | Rest],
- ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = Names} | Rest],
+ ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun) ->
case validate_subject_alt_names(Names) of
true when Names =/= [] ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr0);
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun);
_ ->
- AccErr =
- not_valid({bad_cert, invalid_subject_altname},
- Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify,
- AccErr)
+ UserState = verify_fun(OtpCert, {bad_cert, invalid_subject_altname},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun)
end;
%% This extension SHOULD NOT be marked critical. Its value
%% does not have to be further validated at this point.
-validate_extensions([#'Extension'{extnID = ?'id-ce-issuerAltName',
- extnValue = _} | Rest],
- ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-issuerAltName',
+ extnValue = _} | Rest],
+ ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
%% This extension MUST NOT be marked critical.Its value
%% does not have to be further validated at this point.
-validate_extensions([#'Extension'{extnID = Id,
- extnValue = _,
- critical = false} | Rest],
+validate_extensions(OtpCert, [#'Extension'{extnID = Id,
+ extnValue = _,
+ critical = false} | Rest],
ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr)
+ ExistBasicCon, SelfSigned,
+ UserState, VerifyFun)
when Id == ?'id-ce-subjectKeyIdentifier';
Id == ?'id-ce-authorityKeyIdentifier'->
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
-validate_extensions([#'Extension'{extnID = ?'id-ce-nameConstraints',
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-nameConstraints',
extnValue = NameConst} | Rest],
ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
+ ExistBasicCon, SelfSigned, UserState, VerifyFun) ->
Permitted = NameConst#'NameConstraints'.permittedSubtrees,
Excluded = NameConst#'NameConstraints'.excludedSubtrees,
NewValidationState = add_name_constraints(Permitted, Excluded,
ValidationState),
- validate_extensions(Rest, NewValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
+ validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
-validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies',
- critical = true} | Rest], ValidationState,
- ExistBasicCon, SelfSigned,
- UnknownExtensions, Verify, AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies',
+ critical = true} = Ext| Rest], ValidationState,
+ ExistBasicCon, SelfSigned, UserState0, VerifyFun) ->
%% TODO: Remove this clause when policy handling is
%% fully implemented
- AccErr =
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-
-validate_extensions([#'Extension'{extnID = ?'id-ce-certificatePolicies',
- extnValue = #'PolicyInformation'{
- policyIdentifier = Id,
- policyQualifiers = Qualifier}}
- | Rest], #path_validation_state{valid_policy_tree = Tree}
+ UserState = verify_fun(OtpCert, {extension, Ext},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert,Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies',
+ extnValue = #'PolicyInformation'{
+ policyIdentifier = Id,
+ policyQualifiers = Qualifier}}
+ | Rest], #path_validation_state{valid_policy_tree = Tree}
= ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
+ ExistBasicCon, SelfSigned, UserState, VerifyFun) ->
%% TODO: Policy imp incomplete
NewTree = process_policy_tree(Id, Qualifier, Tree),
- validate_extensions(Rest,
+ validate_extensions(OtpCert, Rest,
ValidationState#path_validation_state{
valid_policy_tree = NewTree},
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr);
+ ExistBasicCon, SelfSigned, UserState, VerifyFun);
-validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints',
- critical = true} | Rest], ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions, Verify,
- AccErr0) ->
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints',
+ critical = true} = Ext | Rest], ValidationState,
+ ExistBasicCon, SelfSigned, UserState0, VerifyFun) ->
%% TODO: Remove this clause when policy handling is
%% fully implemented
- AccErr =
- not_valid({bad_cert, unknown_critical_extension}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
-validate_extensions([#'Extension'{extnID = ?'id-ce-policyConstraints',
- extnValue = #'PolicyConstraints'{
- requireExplicitPolicy = ExpPolicy,
- inhibitPolicyMapping = MapPolicy}}
- | Rest], ValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr) ->
+ UserState = verify_fun(OtpCert, {extension, Ext},
+ UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
+validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-policyConstraints',
+ extnValue = #'PolicyConstraints'{
+ requireExplicitPolicy = ExpPolicy,
+ inhibitPolicyMapping = MapPolicy}}
+ | Rest], ValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun) ->
%% TODO: Policy imp incomplete
- NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy,
+ NewValidationState = add_policy_constraints(ExpPolicy, MapPolicy,
ValidationState),
- validate_extensions(Rest, NewValidationState, ExistBasicCon,
- SelfSigned, UnknownExtensions, Verify, AccErr);
+ validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
+ SelfSigned, UserState, VerifyFun);
-validate_extensions([Extension | Rest], ValidationState,
- ExistBasicCon, SelfSigned, UnknownExtensions,
- Verify, AccErr) ->
- validate_extensions(Rest, ValidationState, ExistBasicCon, SelfSigned,
- [Extension | UnknownExtensions], Verify, AccErr).
+validate_extensions(OtpCert, [#'Extension'{} = Extension | Rest],
+ ValidationState, ExistBasicCon,
+ SelfSigned, UserState0, VerifyFun) ->
+ UserState = verify_fun(OtpCert, {extension, Extension}, UserState0, VerifyFun),
+ validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon, SelfSigned,
+ UserState, VerifyFun).
is_valid_key_usage(KeyUse, Use) ->
lists:member(Use, KeyUse).
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index f9b992afd3..68bf04eeff 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -109,7 +109,8 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
%%--------------------------------------------------------------------
-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
-spec pem_entry_encode(pki_asn1_type(), term(),
- {{Cipher :: string(), Salt :: binary()}, string()}) -> pem_entry().
+ {{Cipher :: string(), Salt :: binary()}, string()}) ->
+ pem_entry().
%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
@@ -440,17 +441,25 @@ pkix_normalize_name(Issuer) ->
CertChain :: [der_encoded()] ,
Options :: list()) ->
{ok, {PublicKeyInfo :: term(),
- PolicyTree :: term(),
- [{bad_cert, Reason :: term()}]}} |
+ PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
%% Description: Performs a basic path validation according to RFC 5280.
%%--------------------------------------------------------------------
-pkix_path_validation(unknown_ca, [Cert | Chain], Options) ->
- case proplists:get_value(verify, Options, true) of
- true ->
- {error, {bad_cert, unknown_ca}};
- false ->
- pkix_path_validation(Cert, Chain, [{acc_errors, [{bad_cert, unknown_ca}]}])
+pkix_path_validation(unknown_ca, [Cert | Chain], Options0) ->
+ {VerifyFun, Userstat0} =
+ proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN),
+ Otpcert = pkix_decode_cert(Cert, otp),
+ Reason = {bad_cert, unknown_ca},
+ try VerifyFun(Otpcert, Reason, Userstat0) of
+ {valid, Userstate} ->
+ Options = proplists:delete(verify_fun, Options0),
+ pkix_path_validation(Otpcert, Chain, [{verify_fun,
+ {VerifyFun, Userstate}}| Options]);
+ {fail, _} ->
+ {error, Reason}
+ catch
+ _:_ ->
+ {error, Reason}
end;
pkix_path_validation(TrustedCert, CertChain, Options) when
is_binary(TrustedCert) -> OtpCert = pkix_decode_cert(TrustedCert,
@@ -462,12 +471,7 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
ValidationState = pubkey_cert:init_validation_state(TrustedCert,
MaxPathDefault,
Options),
- Fun = proplists:get_value(validate_extensions_fun, Options,
- fun(Extensions, State, _, AccError) ->
- {Extensions, State, AccError}
- end),
- Verify = proplists:get_value(verify, Options, true),
- path_validation(CertChain, ValidationState, Fun, Verify).
+ path_validation(CertChain, ValidationState).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -490,38 +494,40 @@ path_validation([], #path_validation_state{working_public_key_algorithm
PublicKey,
working_public_key_parameters
= PublicKeyParams,
- valid_policy_tree = Tree,
- acc_errors = AccErrors
- }, _, _) ->
- {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree, AccErrors}};
+ valid_policy_tree = Tree
+ }) ->
+ {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree}};
path_validation([DerCert | Rest], ValidationState = #path_validation_state{
- max_path_length = Len},
- Fun, Verify) when Len >= 0 ->
- try validate(DerCert,
- ValidationState#path_validation_state{last_cert=Rest=:=[]},
- Fun, Verify) of
+ max_path_length = Len}) when Len >= 0 ->
+ try validate(DerCert,
+ ValidationState#path_validation_state{last_cert=Rest=:=[]}) of
#path_validation_state{} = NewValidationState ->
- path_validation(Rest, NewValidationState, Fun, Verify)
+ path_validation(Rest, NewValidationState)
catch
throw:Reason ->
{error, Reason}
end;
-path_validation(_, _, _, true) ->
- {error, {bad_cert, max_path_length_reached}};
+path_validation([DerCert | _] = Path,
+ #path_validation_state{user_state = UserState0,
+ verify_fun = VerifyFun} =
+ ValidationState) ->
+ Reason = {bad_cert, max_path_length_reached},
+ OtpCert = pkix_decode_cert(DerCert, otp),
+ try VerifyFun(OtpCert, Reason, UserState0) of
+ {valid, UserState} ->
+ path_validation(Path,
+ ValidationState#path_validation_state{
+ max_path_length = 0,
+ user_state = UserState});
+ {fail, _} ->
+ {error, Reason}
+ catch
+ _:_ ->
+ {error, Reason}
+ end.
-path_validation(_, #path_validation_state{working_public_key_algorithm
- = Algorithm,
- working_public_key =
- PublicKey,
- working_public_key_parameters
- = PublicKeyParams,
- valid_policy_tree = Tree,
- acc_errors = AccErrors
- }, _, false) ->
- {ok, {{Algorithm, PublicKey, PublicKeyParams}, Tree,
- [{bad_cert, max_path_length_reached}|AccErrors]}}.
validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
working_public_key = Key,
@@ -531,40 +537,29 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
excluded_subtrees = Exclude,
last_cert = Last,
user_state = UserState0,
- acc_errors = AccErr0} =
- ValidationState0, ValidateExtensionFun, Verify) ->
+ verify_fun = VerifyFun} =
+ ValidationState0) ->
OtpCert = pkix_decode_cert(DerCert, otp),
- %% All validate functions will throw {bad_cert, Reason} if they
- %% fail and Verify = true if Verify = false errors
- %% will be accumulated in the validationstate
- AccErr1 = pubkey_cert:validate_time(OtpCert, AccErr0, Verify),
- AccErr2 = pubkey_cert:validate_issuer(OtpCert, Issuer, AccErr1, Verify),
+ UserState1 = pubkey_cert:validate_time(OtpCert, UserState0, VerifyFun),
+
+ UserState2 = pubkey_cert:validate_issuer(OtpCert, Issuer, UserState1, VerifyFun),
- AccErr3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
- AccErr2, Verify),
- AccErr4 =
- pubkey_cert:validate_revoked_status(OtpCert, Verify, AccErr3),
+ UserState3 = pubkey_cert:validate_names(OtpCert, Permit, Exclude, Last,
+ UserState2,VerifyFun),
+
+ UserState4 = pubkey_cert:validate_revoked_status(OtpCert, UserState3, VerifyFun),
- {ValidationState1, UnknownExtensions0, AccErr5} =
- pubkey_cert:validate_extensions(OtpCert, ValidationState0, Verify,
- AccErr4),
- %% We want the key_usage extension to be checked before we validate
+ {ValidationState1, UserState5} =
+ pubkey_cert:validate_extensions(OtpCert, ValidationState0, UserState4,
+ VerifyFun),
+
+ %% We want the key_usage extension to be checked before we validate
%% the signature.
- AccErr6 =
- pubkey_cert:validate_signature(OtpCert, DerCert, Key, KeyParams,
- AccErr5, Verify),
-
- {UnknownExtensions, UserState, AccErr7} =
- ValidateExtensionFun(UnknownExtensions0, UserState0, Verify, AccErr6),
-
- %% Check that all critical extensions have been handled
- AccErr =
- pubkey_cert:validate_unknown_extensions(UnknownExtensions, AccErr7,
- Verify),
+ UserState = pubkey_cert:validate_signature(OtpCert, DerCert,
+ Key, KeyParams, UserState5, VerifyFun),
ValidationState =
- ValidationState1#path_validation_state{user_state = UserState,
- acc_errors = AccErr},
+ ValidationState1#path_validation_state{user_state = UserState},
pubkey_cert:prepare_for_next_cert(OtpCert, ValidationState).
sized_binary(Binary) when is_binary(Binary) ->
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 09235ff460..46b8c3db8b 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -369,16 +369,35 @@ pkix_path_validation(Config) when is_list(Config) ->
CertK3 = {Cert3,_} = erl_make_certs:make_cert([{issuer, CertK1},
{extensions, [{basic_constraints, false}]}]),
{Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}]),
- {error, E={bad_cert,missing_basic_constraint}} =
+ {error, {bad_cert,missing_basic_constraint}} =
public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], []),
-
- {ok, {_,_,[E]}} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4],
- [{verify,false}]),
-
- {error, {bad_cert,unknown_ca}} = public_key:pkix_path_validation(unknown_ca, [Cert1, Cert3, Cert4], []),
- {ok, {_,_,[{bad_cert,unknown_ca}]}} =
- public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify, false}]),
+ VerifyFunAndState0 = {fun(_,{bad_cert, missing_basic_constraint}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []},
+ {ok, _} =
+ public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4],
+ [{verify_fun, VerifyFunAndState0}]),
+
+ {error, {bad_cert, unknown_ca}} =
+ public_key:pkix_path_validation(unknown_ca, [Cert1, Cert3, Cert4], []),
+
+ VerifyFunAndState1 =
+ {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []},
+
+ {ok, _} =
+ public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify_fun,
+ VerifyFunAndState1}]),
ok.
%%--------------------------------------------------------------------
diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile
index 34781ae720..5109058797 100644
--- a/lib/reltool/test/Makefile
+++ b/lib/reltool/test/Makefile
@@ -74,7 +74,8 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) reltool.spec $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
- $(INSTALL_PROGRAM) rtt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_SCRIPT) rtt $(INSTALL_PROGS) $(RELSYSDIR)
+ $(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
# chmod -f -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index 482fcc0288..cd54f36af0 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -520,7 +520,7 @@ static int do_write(FILETYPE fd, unsigned char *buff, int siz) {
*/
static int my_write(TraceFileData *data, unsigned char *buff, int siz)
{
- int wrote, w;
+ int wrote;
if (data->buff_siz - data->buff_pos >= siz) {
memcpy(data->buff + data->buff_pos, buff, siz);
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 90bb50fdcb..cc01b35b64 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -523,55 +523,55 @@ old_listen(Port, Options) ->
{ok, Pid} = ssl_broker:start_broker(listener),
ssl_broker:listen(Pid, Port, Options).
-handle_options(Opts0, Role) ->
+handle_options(Opts0, _Role) ->
Opts = proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Opts0),
ReuseSessionFun = fun(_, _, _, _) -> true end,
- AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
- (Other, Acc) -> [Other | Acc]
- end,
-
- VerifyFun =
- fun(ErrorList) ->
- case lists:foldl(AcceptBadCa, [], ErrorList) of
- [] -> true;
- [_|_] -> false
- end
- end,
-
- UserFailIfNoPeerCert = validate_option(fail_if_no_peer_cert,
- proplists:get_value(fail_if_no_peer_cert, Opts, false)),
+ VerifyNoneFun =
+ {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []},
+
+ UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false),
+ UserVerifyFun = handle_option(verify_fun, Opts, undefined),
CaCerts = handle_option(cacerts, Opts, undefined),
- {Verify, FailIfNoPeerCert, CaCertDefault} =
+ {Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun} =
%% Handle 0, 1, 2 for backwards compatibility
case proplists:get_value(verify, Opts, verify_none) of
0 ->
- {verify_none, false, ca_cert_default(verify_none, Role, CaCerts)};
+ {verify_none, false,
+ ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
1 ->
- {verify_peer, false, ca_cert_default(verify_peer, Role, CaCerts)};
+ {verify_peer, false,
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
2 ->
- {verify_peer, true, ca_cert_default(verify_peer, Role, CaCerts)};
+ {verify_peer, true,
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
verify_none ->
- {verify_none, false, ca_cert_default(verify_none, Role, CaCerts)};
+ {verify_none, false,
+ ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
verify_peer ->
{verify_peer, UserFailIfNoPeerCert,
- ca_cert_default(verify_peer, Role, CaCerts)};
+ ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
Value ->
throw({error, {eoptions, {verify, Value}}})
- end,
+ end,
CertFile = handle_option(certfile, Opts, ""),
SSLOptions = #ssl_options{
versions = handle_option(versions, Opts, []),
verify = validate_option(verify, Verify),
- verify_fun = handle_option(verify_fun, Opts, VerifyFun),
+ verify_fun = VerifyFun,
fail_if_no_peer_cert = FailIfNoPeerCert,
verify_client_once = handle_option(verify_client_once, Opts, false),
- validate_extensions_fun = handle_option(validate_extensions_fun, Opts, undefined),
depth = handle_option(depth, Opts, 1),
cert = handle_option(cert, Opts, undefined),
certfile = CertFile,
@@ -580,6 +580,7 @@ handle_options(Opts0, Role) ->
password = handle_option(password, Opts, ""),
cacerts = CaCerts,
cacertfile = handle_option(cacertfile, Opts, CaCertDefault),
+ dh = handle_option(dh, Opts, undefined),
dhfile = handle_option(dhfile, Opts, undefined),
ciphers = handle_option(ciphers, Opts, []),
%% Server side option
@@ -591,10 +592,10 @@ handle_options(Opts0, Role) ->
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
- SslOptions = [versions, verify, verify_fun, validate_extensions_fun,
+ SslOptions = [versions, verify, verify_fun,
fail_if_no_peer_cert, verify_client_once,
depth, cert, certfile, key, keyfile,
- password, cacerts, cacertfile, dhfile, ciphers,
+ password, cacerts, cacertfile, dh, dhfile, ciphers,
debug, reuse_session, reuse_sessions, ssl_imp,
cb_info, renegotiate_at, secure_renegotiate],
@@ -618,7 +619,21 @@ validate_option(ssl_imp, Value) when Value == new; Value == old ->
validate_option(verify, Value)
when Value == verify_none; Value == verify_peer ->
Value;
-validate_option(verify_fun, Value) when is_function(Value) ->
+validate_option(verify_fun, undefined) ->
+ undefined;
+%% Backwards compatibility
+validate_option(verify_fun, Fun) when is_function(Fun) ->
+ {fun(_,{bad_cert, _} = Reason, OldFun) ->
+ case OldFun([Reason]) of
+ true ->
+ {valid, OldFun};
+ false ->
+ {fail, Reason}
+ end;
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, Fun};
+validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) ->
Value;
validate_option(fail_if_no_peer_cert, Value)
when Value == true; Value == false ->
@@ -626,9 +641,6 @@ validate_option(fail_if_no_peer_cert, Value)
validate_option(verify_client_once, Value)
when Value == true; Value == false ->
Value;
-
-validate_option(validate_extensions_fun, Value) when Value == undefined; is_function(Value) ->
- Value;
validate_option(depth, Value) when is_integer(Value),
Value >= 0, Value =< 255->
Value;
@@ -658,6 +670,9 @@ validate_option(cacertfile, undefined) ->
"";
validate_option(cacertfile, Value) when is_list(Value), Value =/= "" ->
Value;
+validate_option(dh, Value) when Value == undefined;
+ is_binary(Value) ->
+ Value;
validate_option(dhfile, undefined = Value) ->
Value;
validate_option(dhfile, Value) when is_list(Value), Value =/= "" ->
@@ -720,12 +735,11 @@ ca_cert_default(_,_, [_|_]) ->
undefined;
ca_cert_default(verify_none, _, _) ->
undefined;
-%% Client may leave verification up to the user
-ca_cert_default(verify_peer, client,_) ->
+ca_cert_default(verify_peer, {Fun,_}, _) when is_function(Fun) ->
undefined;
-%% Server that wants to verify_peer must have
+%% Server that wants to verify_peer and has no verify_fun must have
%% some trusted certs.
-ca_cert_default(verify_peer, server, _) ->
+ca_cert_default(verify_peer, undefined, _) ->
"".
emulated_options() ->
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 5026c760bd..6cf57ced81 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -34,7 +34,8 @@
-export([trusted_cert_and_path/2,
certificate_chain/2,
file_to_certificats/1,
- validate_extensions/6,
+ %validate_extensions/6,
+ validate_extension/3,
is_valid_extkey_usage/2,
is_valid_key_usage/2,
select_extension/2,
@@ -110,32 +111,25 @@ file_to_certificats(File) ->
{ok, List} = ssl_manager:cache_pem_file(File),
[Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
--spec validate_extensions([#'Extension'{}], term(), [#'Extension'{}],
- boolean(), list(), client | server) -> {[#'Extension'{}], term(), list()}.
+-spec validate_extension(term(), #'Extension'{}, term()) -> {valid, term()} |
+ {fail, tuple()} |
+ {unknown, term()}.
%%
%% Description: Validates ssl/tls specific extensions
%%--------------------------------------------------------------------
-validate_extensions([], ValidationState, UnknownExtensions, _, AccErr, _) ->
- {UnknownExtensions, ValidationState, AccErr};
-
-validate_extensions([#'Extension'{extnID = ?'id-ce-extKeyUsage',
- extnValue = KeyUse,
- critical = true} | Rest],
- ValidationState, UnknownExtensions, Verify, AccErr0, Role) ->
+validate_extension(_,{extension, #'Extension'{extnID = ?'id-ce-extKeyUsage',
+ extnValue = KeyUse,
+ critical = true}}, Role) ->
case is_valid_extkey_usage(KeyUse, Role) of
true ->
- validate_extensions(Rest, ValidationState, UnknownExtensions,
- Verify, AccErr0, Role);
+ {valid, Role};
false ->
- AccErr =
- not_valid_extension({bad_cert, invalid_ext_key_usage}, Verify, AccErr0),
- validate_extensions(Rest, ValidationState, UnknownExtensions, Verify, AccErr, Role)
+ {fail, {bad_cert, invalid_ext_key_usage}}
end;
-
-validate_extensions([Extension | Rest], ValidationState, UnknownExtensions,
- Verify, AccErr, Role) ->
- validate_extensions(Rest, ValidationState, [Extension | UnknownExtensions],
- Verify, AccErr, Role).
+validate_extension(_, {bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+validate_extension(_, _, Role) ->
+ {unknown, Role}.
%%--------------------------------------------------------------------
-spec is_valid_key_usage(list(), term()) -> boolean().
@@ -248,8 +242,3 @@ is_valid_extkey_usage(KeyUse, client) ->
is_valid_extkey_usage(KeyUse, server) ->
%% Server wants to verify client
is_valid_key_usage(KeyUse, ?'id-kp-clientAuth').
-
-not_valid_extension(Error, true, _) ->
- throw(Error);
-not_valid_extension(Error, false, AccErrors) ->
- [Error | AccErrors].
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index c004effb85..c94199c336 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -500,8 +500,7 @@ certify(#certificate{} = Cert,
ssl_options = Opts} = State) ->
case ssl_handshake:certify(Cert, CertDbRef, Opts#ssl_options.depth,
Opts#ssl_options.verify,
- Opts#ssl_options.verify_fun,
- Opts#ssl_options.validate_extensions_fun, Role) of
+ Opts#ssl_options.verify_fun, Role) of
{PeerCert, PublicKeyInfo} ->
handle_peer_cert(PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false});
@@ -1035,7 +1034,7 @@ ssl_init(SslOpts, Role) ->
PrivateKey =
init_private_key(SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(SslOpts#ssl_options.dhfile, Role),
+ DHParams = init_diffie_hellman(SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
{ok, CertDbRef, CacheRef, OwnCert, PrivateKey, DHParams}.
@@ -1112,11 +1111,13 @@ file_error(Line, Error, Reason, File, Throw, Stack) ->
error_logger:error_report(Report),
throw(Throw).
-init_diffie_hellman(_, client) ->
+init_diffie_hellman(Params, _,_) when is_binary(Params)->
+ public_key:der_decode('DHParameter', Params);
+init_diffie_hellman(_,_, client) ->
undefined;
-init_diffie_hellman(undefined, _) ->
+init_diffie_hellman(_,undefined, _) ->
?DEFAULT_DIFFIE_HELLMAN_PARAMS;
-init_diffie_hellman(DHParamFile, server) ->
+init_diffie_hellman(_, DHParamFile, server) ->
try
{ok, List} = ssl_manager:cache_pem_file(DHParamFile),
case [Entry || Entry = {'DHParameter', _ , _} <- List] of
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index add5147fb4..99bc47f04b 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -32,15 +32,13 @@
-include_lib("public_key/include/public_key.hrl").
-export([master_secret/4, client_hello/5, server_hello/4, hello/4,
- hello_request/0, certify/7, certificate/3,
- client_certificate_verify/6,
- certificate_verify/6, certificate_request/2,
- key_exchange/2, server_key_exchange_hash/2, finished/4,
- verify_connection/5,
- get_tls_handshake/2, decode_client_key/3,
- server_hello_done/0, sig_alg/1,
- encode_handshake/3, init_hashes/0,
- update_hashes/2, decrypt_premaster_secret/2]).
+ hello_request/0, certify/6, certificate/3,
+ client_certificate_verify/6, certificate_verify/6,
+ certificate_request/2, key_exchange/2, server_key_exchange_hash/2,
+ finished/4, verify_connection/5, get_tls_handshake/2,
+ decode_client_key/3, server_hello_done/0, sig_alg/1,
+ encode_handshake/3, init_hashes/0, update_hashes/2,
+ decrypt_premaster_secret/2]).
-type tls_handshake() :: #client_hello{} | #server_hello{} |
#server_hello_done{} | #certificate{} | #certificate_request{} |
@@ -177,59 +175,55 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
%%--------------------------------------------------------------------
-spec certify(#certificate{}, term(), integer() | nolimit,
- verify_peer | verify_none, fun(), fun(),
+ verify_peer | verify_none, {fun(), term},
client | server) -> {der_cert(), public_key_info()} | #alert{}.
%%
%% Description: Handles a certificate handshake message
%%--------------------------------------------------------------------
-certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
- MaxPathLen, Verify, VerifyFun, ValidateFun, Role) ->
+certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
+ MaxPathLen, _Verify, VerifyFunAndState, Role) ->
[PeerCert | _] = ASN1Certs,
- VerifyBool = verify_bool(Verify),
- ValidateExtensionFun =
- case ValidateFun of
+ ValidationFunAndState =
+ case VerifyFunAndState of
undefined ->
- fun(Extensions, ValidationState, Verify0, AccError) ->
- ssl_certificate:validate_extensions(Extensions, ValidationState,
- [], Verify0, AccError, Role)
- end;
- Fun ->
- fun(Extensions, ValidationState, Verify0, AccError) ->
- {NewExtensions, NewValidationState, NewAccError}
- = ssl_certificate:validate_extensions(Extensions, ValidationState,
- [], Verify0, AccError, Role),
- Fun(NewExtensions, NewValidationState, Verify0, NewAccError)
- end
+ {fun(OtpCert, ExtensionOrError, SslState) ->
+ ssl_certificate:validate_extension(OtpCert,
+ ExtensionOrError, SslState)
+ end, Role};
+ {Fun, UserState0} ->
+ {fun(OtpCert, ExtensionOrError, {SslState, UserState}) ->
+ case ssl_certificate:validate_extension(OtpCert,
+ ExtensionOrError,
+ SslState) of
+ {valid, _} ->
+ apply_user_fun(Fun, OtpCert,
+ ExtensionOrError, UserState,
+ SslState);
+ {fail, Reason} ->
+ apply_user_fun(Fun, OtpCert, Reason, UserState,
+ SslState);
+ {unknown, _} ->
+ apply_user_fun(Fun, OtpCert,
+ ExtensionOrError, UserState, SslState)
+ end
+ end, {Role, UserState0}}
end,
- try
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef) of
- {TrustedErlCert, CertPath} ->
- Result = public_key:pkix_path_validation(TrustedErlCert,
- CertPath,
- [{max_path_length,
- MaxPathLen},
- {verify, VerifyBool},
- {validate_extensions_fun,
- ValidateExtensionFun}]),
- case Result of
- {error, Reason} ->
- path_validation_alert(Reason, Verify);
- {ok, {PublicKeyInfo,_, []}} ->
- {PeerCert, PublicKeyInfo};
- {ok, {PublicKeyInfo,_, AccErrors = [Error | _]}} ->
- case VerifyFun(AccErrors) of
- true ->
- {PeerCert, PublicKeyInfo};
- false ->
- path_validation_alert(Error, Verify)
- end
- end
- catch
- throw:Alert ->
- Alert
+
+ {TrustedErlCert, CertPath} =
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef),
+
+ case public_key:pkix_path_validation(TrustedErlCert,
+ CertPath,
+ [{max_path_length,
+ MaxPathLen},
+ {verify_fun, ValidationFunAndState}]) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, Reason} ->
+ path_validation_alert(Reason)
end.
-
+
%%--------------------------------------------------------------------
-spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}.
%%
@@ -490,26 +484,21 @@ get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length),
get_tls_handshake_aux(Data, Acc) ->
{lists:reverse(Acc), Data}.
-verify_bool(verify_peer) ->
- true;
-verify_bool(verify_none) ->
- false.
-
-path_validation_alert({bad_cert, cert_expired}, _) ->
+path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
-path_validation_alert({bad_cert, invalid_issuer}, _) ->
+path_validation_alert({bad_cert, invalid_issuer}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, invalid_signature} , _) ->
+path_validation_alert({bad_cert, invalid_signature}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, name_not_permitted}, _) ->
+path_validation_alert({bad_cert, name_not_permitted}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
-path_validation_alert({bad_cert, unknown_critical_extension}, _) ->
+path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
-path_validation_alert({bad_cert, cert_revoked}, _) ->
+path_validation_alert({bad_cert, cert_revoked}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
-path_validation_alert({bad_cert, unknown_ca}, _) ->
+path_validation_alert({bad_cert, unknown_ca}) ->
?ALERT_REC(?FATAL, ?UNKNOWN_CA);
-path_validation_alert(_, _) ->
+path_validation_alert(_) ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE).
select_session(Hello, Port, Session, Version,
@@ -1132,3 +1121,13 @@ key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
?KEY_EXCHANGE_DIFFIE_HELLMAN;
key_exchange_alg(_) ->
?NULL.
+
+apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) ->
+ case Fun(OtpCert, ExtensionOrError, UserState0) of
+ {valid, UserState} ->
+ {valid, {SslState, UserState}};
+ {fail, _} = Fail ->
+ Fail;
+ {unknown, UserState} ->
+ {unknown, {SslState, UserState}}
+ end.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 3862dc75de..ddb05e70f6 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -69,6 +69,7 @@
password, %
cacerts, % [der_encoded()]
cacertfile, % file()
+ dh, % der_encoded()
dhfile, % file()
ciphers, %
%% Local policy for the server if it want's to reuse the session
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 6db13e5b7a..25e7445180 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -113,7 +113,7 @@ select_session(Sessions, #ssl_options{ciphers = Ciphers,
List ->
hd(List)
end.
-
+
%% If we can not generate a not allready in use session ID in
%% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The
%% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 1013f2bb6e..1e96880801 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -232,10 +232,11 @@ all(suite) ->
server_renegotiate, client_renegotiate_reused_session,
server_renegotiate_reused_session, client_no_wrap_sequence_number,
server_no_wrap_sequence_number, extended_key_usage,
- validate_extensions_fun, no_authority_key_identifier,
+ no_authority_key_identifier,
invalid_signature_client, invalid_signature_server, cert_expired,
client_with_cert_cipher_suites_handshake, unknown_server_ca_fail,
- unknown_server_ca_accept, der_input
+ der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer,
+ unknown_server_ca_accept_backwardscompatibilty
].
%% Test cases starts here.
@@ -1260,7 +1261,6 @@ eoptions(Config) when is_list(Config) ->
{verify_fun, function},
{fail_if_no_peer_cert, 0},
{verify_client_once, 1},
- {validate_extensions_fun, function},
{depth, four},
{certfile, 'cert.pem'},
{keyfile,'key.pem' },
@@ -2271,14 +2271,7 @@ client_verify_none_active_once(Config) when is_list(Config) ->
{mfa, {?MODULE, send_recv_result_active_once, []}},
{options, [{active, once} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- %% TODO: send message to test process to make sure
- %% verifyfun has beeen run as it has the same behavior as
- %% the default fun
- VerifyFun = fun([{bad_cert, unknown_ca}]) ->
- true;
- (_) ->
- false
- end,
+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2286,8 +2279,7 @@ client_verify_none_active_once(Config) when is_list(Config) ->
send_recv_result_active_once,
[]}},
{options, [{active, once},
- {verify, verify_none},
- {verify_fun, VerifyFun}
+ {verify, verify_none}
| ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -2578,41 +2570,6 @@ extended_key_usage(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-validate_extensions_fun(doc) ->
- ["Test that it is possible to specify a validate_extensions_fun"];
-
-validate_extensions_fun(suite) ->
- [];
-
-validate_extensions_fun(Config) when is_list(Config) ->
- ClientOpts = ?config(client_verification_opts, Config),
- ServerOpts = ?config(server_verification_opts, Config),
-
- Fun = fun(Extensions, State, _, AccError) ->
- {Extensions, State, AccError}
- end,
-
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, send_recv_result_active, []}},
- {options, [{validate_extensions_fun, Fun},
- {verify, verify_peer} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, send_recv_result_active, []}},
- {options,[{validate_extensions_fun, Fun} | ClientOpts]}]),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
no_authority_key_identifier(doc) ->
["Test cert that does not have authorityKeyIdentifier extension"
" but are present in trusted certs db."];
@@ -2899,24 +2856,34 @@ unknown_server_ca_fail(Config) when is_list(Config) ->
no_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
+
+ FunAndState = {fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []},
+
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib,
no_result, []}},
{options,
- [{verify, verify_peer}| ClientOpts]}]),
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error,"unknown ca"}, Client, {error, "unknown ca"}),
+ ssl_test_lib:check_result(Server, {error,"unknown ca"},
+ Client, {error, "unknown ca"}),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-unknown_server_ca_accept(doc) ->
+unknown_server_ca_accept_verify_none(doc) ->
["Test that the client succeds if the ca is unknown in verify_none mode"];
-unknown_server_ca_accept(suite) ->
+unknown_server_ca_accept_verify_none(suite) ->
[];
-unknown_server_ca_accept(Config) when is_list(Config) ->
+unknown_server_ca_accept_verify_none(Config) when is_list(Config) ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -2937,6 +2904,83 @@ unknown_server_ca_accept(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+%%--------------------------------------------------------------------
+unknown_server_ca_accept_verify_peer(doc) ->
+ ["Test that the client succeds if the ca is unknown in verify_peer mode"
+ " with a verify_fun that accepts the unknown ca error"];
+unknown_server_ca_accept_verify_peer(suite) ->
+ [];
+unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState}
+ end, []},
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+unknown_server_ca_accept_backwardscompatibilty(doc) ->
+ ["Test that the client succeds if the ca is unknown in verify_none mode"];
+unknown_server_ca_accept_backwardscompatibilty(suite) ->
+ [];
+unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc;
+ (Other, Acc) -> [Other | Acc]
+ end,
+ VerifyFun =
+ fun(ErrorList) ->
+ case lists:foldl(AcceptBadCa, [], ErrorList) of
+ [] -> true;
+ [_|_] -> false
+ end
+ end,
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ send_recv_result_active, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, VerifyFun}| ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
der_input(doc) ->
@@ -2946,14 +2990,20 @@ der_input(suite) ->
[];
der_input(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ DHParamFile = filename:join(DataDir, "dHParam.pem"),
SeverVerifyOpts = ?config(server_verification_opts, Config),
- {ServerCert, ServerKey, ServerCaCerts} = der_input_opts(SeverVerifyOpts),
+ {ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ SeverVerifyOpts]),
ClientVerifyOpts = ?config(client_verification_opts, Config),
- {ClientCert, ClientKey, ClientCaCerts} = der_input_opts(ClientVerifyOpts),
+ {ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
+ ClientVerifyOpts]),
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
{cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCaCerts}],
ClientOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
{cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCaCerts}],
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -2975,14 +3025,16 @@ der_input_opts(Opts) ->
Certfile = proplists:get_value(certfile, Opts),
CaCertsfile = proplists:get_value(cacertfile, Opts),
Keyfile = proplists:get_value(keyfile, Opts),
+ Dhfile = proplists:get_value(dhfile, Opts),
[{_, Cert, _}] = ssl_test_lib:pem_to_der(Certfile),
[{_, Key, _}] = ssl_test_lib:pem_to_der(Keyfile),
+ [{_, DHParams, _}] = ssl_test_lib:pem_to_der(Dhfile),
CaCerts =
lists:map(fun(Entry) ->
{_, CaCert, _} = Entry,
CaCert
end, ssl_test_lib:pem_to_der(CaCertsfile)),
- {Cert, {rsa, Key}, CaCerts}.
+ {Cert, {rsa, Key}, CaCerts, DHParams}.
%%--------------------------------------------------------------------
%%% Internal functions
diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml
index 7c821d2efc..cfb18ec131 100644
--- a/lib/stdlib/doc/src/erl_id_trans.xml
+++ b/lib/stdlib/doc/src/erl_id_trans.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2007</year>
+ <year>2010</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -70,7 +70,8 @@
<section>
<title>See Also</title>
- <p><seealso marker="erl_parse">erl_parse(3)</seealso>, compile(3).</p>
+ <p><seealso marker="erl_parse">erl_parse(3)</seealso>,
+ <seealso marker="compiler:compile">compile(3)</seealso>.</p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml
index 6a7d37765c..8639d678fa 100644
--- a/lib/stdlib/doc/src/erl_lint.xml
+++ b/lib/stdlib/doc/src/erl_lint.xml
@@ -96,8 +96,8 @@
<p>The <c>AbsForms</c> of a module which comes from a file
that is read through <c>epp</c>, the Erlang pre-processor,
can come from many files. This means that any references to
- errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso> The warnings and
- errors returned have the following format:
+ errors must include the file name (see <seealso marker="epp">epp(3)</seealso>, or parser <seealso marker="erl_parse">erl_parse(3)</seealso>).
+ The warnings and errors returned have the following format:
</p>
<code type="none">
[{FileName2,[ErrorInfo]}] </code>
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index ae8a8afd5c..18b592deea 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -39,7 +39,7 @@
expressions, or terms. The Abstract Format is described in the ERTS
User's Guide.
Note that a token list must end with the <em>dot</em> token in order
- to be acceptable to the parse functions (see erl_scan).</p>
+ to be acceptable to the parse functions (see <seealso marker="erl_scan">erl_scan(3)</seealso>).</p>
</description>
<funcs>
<func>
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index b3ad7aaf46..92c4eb4f4c 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -220,7 +220,7 @@
follows:</p>
<code type="none">
flatmap(Fun, List1) ->
- append(map(Fun, List1))</code>
+ append(map(Fun, List1)).</code>
<p>Example:</p>
<pre>
> <input>lists:flatmap(fun(X)->[X,X] end, [a,b,c]).</input>
@@ -523,7 +523,7 @@ flatmap(Fun, List1) ->
<v>&nbsp;A = B = term()</v>
</type>
<desc>
- <p><c>mapfold</c> combines the operations of <c>map/2</c> and
+ <p><c>mapfoldl</c> combines the operations of <c>map/2</c> and
<c>foldl/3</c> into one pass. An example, summing
the elements in a list and double them at the same time:</p>
<pre>
@@ -543,7 +543,7 @@ flatmap(Fun, List1) ->
<v>&nbsp;A = B = term()</v>
</type>
<desc>
- <p><c>mapfold</c> combines the operations of <c>map/2</c> and
+ <p><c>mapfoldr</c> combines the operations of <c>map/2</c> and
<c>foldr/3</c> into one pass.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index 10ead62073..8cbfb9387b 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -34,7 +34,7 @@
<module>sys</module>
<modulesummary>A Functional Interface to System Messages</modulesummary>
<description>
- <p>This module contains functions for sending system messages used by programs, and messaged used for debugging purposes.
+ <p>This module contains functions for sending system messages used by programs, and messages used for debugging purposes.
</p>
<p>Functions used for implementation of processes
should also understand system messages such as debugging
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index d55a3a597d..3dca55178d 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -139,7 +139,7 @@ release_tests_spec: opt
$(TARGET_FILES) $(TS_TARGET_FILES) \
$(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \
$(RELEASE_PATH)/test_server
- $(INSTALL_PROGRAM) $(PROGRAMS) $(RELEASE_PATH)/test_server
+ $(INSTALL_SCRIPT) $(PROGRAMS) $(RELEASE_PATH)/test_server
release_docs_spec:
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
index 702d73f5af..fcb1282d16 100644
--- a/lib/test_server/test/Makefile
+++ b/lib/test_server/test/Makefile
@@ -88,7 +88,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_PROGRAM) test_server.spec $(RELSYSDIR)
+ $(INSTALL_DATA) test_server.spec $(RELSYSDIR)
chmod -f -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/tools/doc/src/erlang_mode.xml b/lib/tools/doc/src/erlang_mode.xml
index 912c442153..c21afc1f9b 100644
--- a/lib/tools/doc/src/erlang_mode.xml
+++ b/lib/tools/doc/src/erlang_mode.xml
@@ -173,7 +173,7 @@
sum(L) -> sum(L, 0).
sum([H|T], Sum) -> sum(T, Sum + H);
- sum([], Sum) -> Sum."</code>
+ sum([], Sum) -> Sum.</code>
</item>
</list>
</section>
diff --git a/lib/tools/doc/src/erlang_mode_chapter.xml b/lib/tools/doc/src/erlang_mode_chapter.xml
index b22c6b1809..8aabd6ae74 100644
--- a/lib/tools/doc/src/erlang_mode_chapter.xml
+++ b/lib/tools/doc/src/erlang_mode_chapter.xml
@@ -45,7 +45,7 @@
<section>
<title>Elisp</title>
- <p>There are two Elsip modules include in this tool package
+ <p>There are two Elisp modules included in this tool package
for Emacs. There is erlang.el that defines the actual erlang mode
and there is erlang-start.el that makes some nice initializations.</p>
</section>
diff --git a/lib/wx/test/Makefile b/lib/wx/test/Makefile
index 71b79aa272..dfec4bb695 100644
--- a/lib/wx/test/Makefile
+++ b/lib/wx/test/Makefile
@@ -63,7 +63,7 @@ release_spec:
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) wx.spec wx_test_lib.hrl $(ErlSrc) $(ErlTargets) $(RELSYSDIR)
- $(INSTALL_PROGRAM) wxt $(RELSYSDIR)
+ $(INSTALL_SCRIPT) wxt $(RELSYSDIR)
release_docs_spec:
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 4e5cc59d8f..e2e6f95c4a 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -2602,8 +2602,7 @@ scan_reference("#x" ++ T, S0) ->
%% [66] CharRef
?bump_col(1),
if hd(T) /= $; ->
- {[Ch], T2, S2} = scan_char_ref_hex(T, S, 0),
- {to_char_set(S2#xmerl_scanner.encoding,Ch),T2,S2};
+ scan_char_ref_hex(T, S, 0);
true ->
?fatal(invalid_char_ref, S)
end;
@@ -3452,14 +3451,14 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
%% {system,URI} or {public,URI}
%% Included in literal.
{ExpRef,Sx}=fetch_not_parse(Tuple,S1),
- {EntV,_,_S2} =
- scan_entity_value(ExpRef, Sx, no_delim,[],
+ {EntV, _, S5} =
+ scan_entity_value(ExpRef, Sx, no_delim,[],
PERefName,parameter,[]),
%% should do an update Write(parameter_entity)
%% so next expand_pe_reference is faster
- {EntV,_S2};
+ {string_to_char_set(S5#xmerl_scanner.encoding, EntV), S5};
ExpRef ->
- {ExpRef,S1}
+ {string_to_char_set(S1#xmerl_scanner.encoding, ExpRef) ,S1}
end,
%% single or duoble qoutes are not treated as delimeters
%% in passages "included in literal"
@@ -4020,12 +4019,12 @@ utf8_2_ucs([A|Rest]) when A < 16#80 ->
utf8_2_ucs([A|Rest]) ->
{{error,{bad_character,A}},Rest}.
-to_char_set("iso-10646-utf-1",Ch) ->
- [Ch];
-to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined ->
- ucs_2_utf8(Ch);
-to_char_set(_,Ch) ->
- [Ch].
+%% to_char_set("iso-10646-utf-1",Ch) ->
+%% [Ch];
+%% to_char_set(UTF8,Ch) when UTF8 =:= "utf-8"; UTF8 =:= undefined ->
+%% ucs_2_utf8(Ch);
+%% to_char_set(_,Ch) ->
+%% [Ch].
ucs_2_utf8(Ch) when Ch < 128 ->
%% 0vvvvvvv