Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
BIND
Commits
c315e5cf
Commit
c315e5cf
authored
Jun 04, 2004
by
Mark Andrews
Browse files
1648. [func] Update dnssec-lookaside named.conf syntax to support
multiple dnssec-lookaside namespaces (not yet implemented).
parent
f66cd386
Changes
8
Hide whitespace changes
Inline
Side-by-side
CHANGES
View file @
c315e5cf
1649. [placeholder] rt11206
1648. [placeholder] rt11439
1648. [func] Update dnssec-lookaside named.conf syntax to support
multiple dnssec-lookaside namespaces (not yet
implemented).
1647. [placeholder] rt11445
...
...
bin/named/server.c
View file @
c315e5cf
...
...
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.42
6
2004/0
5/14 00:51:52
marka Exp $ */
/* $Id: server.c,v 1.42
7
2004/0
6/04 02:31:40
marka Exp $ */
#include <config.h>
...
...
@@ -1171,14 +1171,42 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
obj
=
NULL
;
result
=
ns_config_get
(
maps
,
"dnssec-lookaside"
,
&
obj
);
if
(
result
==
ISC_R_SUCCESS
)
{
const
char
*
dlv
;
isc_buffer_t
b
;
dlv
=
cfg_obj_asstring
(
obj
);
isc_buffer_init
(
&
b
,
dlv
,
strlen
(
dlv
));
isc_buffer_add
(
&
b
,
strlen
(
dlv
));
CHECK
(
dns_name_fromtext
(
dns_fixedname_name
(
&
view
->
dlv_fixed
),
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
));
view
->
dlv
=
dns_fixedname_name
(
&
view
->
dlv_fixed
);
for
(
element
=
cfg_list_first
(
obj
);
element
!=
NULL
;
element
=
cfg_list_next
(
element
))
{
const
char
*
str
;
isc_buffer_t
b
;
dns_name_t
*
dlv
;
obj
=
cfg_listelt_value
(
element
);
#if 0
dns_fixedname_t fixed;
dns_name_t *name;
/*
* When we support multiple dnssec-lookaside
* entries this is how to find the domain to be
* checked. XXXMPA
*/
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
str = cfg_obj_asstring(cfg_tuple_get(obj,
"domain"));
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
CHECK(dns_name_fromtext(name, &b, dns_rootname,
ISC_TRUE, NULL));
#endif
str
=
cfg_obj_asstring
(
cfg_tuple_get
(
obj
,
"trust-anchor"
));
isc_buffer_init
(
&
b
,
str
,
strlen
(
str
));
isc_buffer_add
(
&
b
,
strlen
(
str
));
dlv
=
dns_fixedname_name
(
&
view
->
dlv_fixed
);
CHECK
(
dns_name_fromtext
(
dlv
,
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
));
view
->
dlv
=
dns_fixedname_name
(
&
view
->
dlv_fixed
);
}
}
else
view
->
dlv
=
NULL
;
...
...
bin/tests/system/dlv/ns5/named.conf
View file @
c315e5cf
...
...
@@ -14,7 +14,7 @@
*
PERFORMANCE
OF
THIS
SOFTWARE
.
*/
/* $
Id
:
named
.
conf
,
v
1
.
2
2004
/
0
5
/
14
04
:
58
:
23
marka
Exp
$ */
/* $
Id
:
named
.
conf
,
v
1
.
3
2004
/
0
6
/
04
02
:
31
:
41
marka
Exp
$ */
/*
*
Choose
a
keyname
that
is
unlikely
to
clash
with
any
real
key
names
.
...
...
@@ -58,7 +58,7 @@ options {
recursion
yes
;
notify
yes
;
dnssec
-
enable
yes
;
dnssec
-
lookaside
"dlv.utld"
;
dnssec
-
lookaside
"."
trust
-
anchor
"dlv.utld"
;
};
zone
"."
{
type
hint
;
file
"hints"
; };
bin/tests/system/dnssec/ns6/named.conf
View file @
c315e5cf
...
...
@@ -14,7 +14,7 @@
*
PERFORMANCE
OF
THIS
SOFTWARE
.
*/
/* $
Id
:
named
.
conf
,
v
1
.
6
2004
/
0
3
/
10
02
:
19
:
54
marka
Exp
$ */
/* $
Id
:
named
.
conf
,
v
1
.
7
2004
/
0
6
/
04
02
:
31
:
41
marka
Exp
$ */
//
NS6
...
...
@@ -32,7 +32,7 @@ options {
notify
yes
;
disable
-
algorithms
. {
DSA
; };
dnssec
-
enable
yes
;
dnssec
-
lookaside
dlv
;
dnssec
-
lookaside
.
trust
-
anchor
dlv
;
};
zone
"."
{
...
...
doc/arm/Bv9ARM-book.xml
View file @
c315e5cf
...
...
@@ -2,7 +2,7 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
<!-- File: $Id: Bv9ARM-book.xml,v 1.24
6
2004/0
5/19 23:42:05
marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.24
7
2004/0
6/04 02:31:42
marka Exp $ -->
<book>
<title>
BIND 9 Administrator Reference Manual
</title>
...
...
@@ -2758,7 +2758,7 @@ statement in the <filename>named.conf</filename> file:</para>
<optional>
use-id-pool
<replaceable>
yes_or_no
</replaceable>
;
</optional>
<optional>
maintain-ixfr-base
<replaceable>
yes_or_no
</replaceable>
;
</optional>
<optional>
dnssec-enable
<replaceable>
yes_or_no
</replaceable>
;
</optional>
<optional>
dnssec-lookaside
<replaceable>
domain
</replaceable>
;
</optional>
<optional>
dnssec-lookaside
<replaceable>
domain
</replaceable>
trust-anchor
<replaceable>
domain
</replaceable>
;
</optional>
<optional>
dnssec-must-be-secure
<replaceable>
domain yes_or_no
</replaceable>
;
</optional>
<optional>
forward (
<replaceable>
only
</replaceable>
|
<replaceable>
first
</replaceable>
);
</optional>
<optional>
forwarders {
<replaceable>
ip_addr
</replaceable>
<optional>
port
<replaceable>
ip_port
</replaceable></optional>
;
<optional>
<replaceable>
ip_addr
</replaceable>
<optional>
port
<replaceable>
ip_port
</replaceable></optional>
; ...
</optional>
};
</optional>
...
...
@@ -2985,10 +2985,12 @@ Only the most specific will be applied.
<listitem><para>
When set
<command>
dnssec-lookaside
</command>
provides the
validator with an alternate method to validate DNSKEY records at the
top of a zone. When set the domain specified by
<command>
dnssec-lookaside
</command>
is appended to DNSKEY's
name and a DLV record is looked up. If the DLV record validates
a DNSKEY (similarly to the way a DS record does) the DNSKEY RRset is deemed to be trusted.
top of a zone. When a DNSKEY is at or below a domain specified by the
deepest
<command>
dnssec-lookaside
</command>
, and the normal dnssec validation
has left the key untrusted, the trust-anchor will be append to the key
name and a DLV record will be looked up to see if it can validate the
key. If the DLV record validates a DNSKEY (similarly to the way a DS
record does) the DNSKEY RRset is deemed to be trusted.
</para></listitem></varlistentry>
<varlistentry><term><command>
dnssec-must-be-secure
</command></term>
...
...
doc/misc/options
View file @
c315e5cf
...
...
@@ -82,7 +82,7 @@ options {
root-delegation-only [ exclude { <quoted_string>; ... } ];
disable-algorithms <string> { <string>; ... };
dnssec-enable <boolean>;
dnssec-lookaside <string>;
dnssec-lookaside
<string> trust-anchor
<string>;
dnssec-must-be-secure <string> <boolean>;
allow-query { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
...
...
@@ -262,7 +262,7 @@ view <string> <optional_class> {
root-delegation-only [ exclude { <quoted_string>; ... } ];
disable-algorithms <string> { <string>; ... };
dnssec-enable <boolean>;
dnssec-lookaside <string>;
dnssec-lookaside
<string> trust-anchor
<string>;
dnssec-must-be-secure <string> <boolean>;
allow-query { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
...
...
lib/bind9/check.c
View file @
c315e5cf
...
...
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.4
6
2004/0
5/17
0
5
:3
7
:4
1
marka Exp $ */
/* $Id: check.c,v 1.4
7
2004/0
6/04
0
2
:3
1
:4
3
marka Exp $ */
#include <config.h>
...
...
@@ -279,6 +279,39 @@ disabled_algorithms(cfg_obj_t *disabled, isc_log_t *logctx) {
return
(
result
);
}
static
isc_result_t
nameexist
(
cfg_obj_t
*
obj
,
const
char
*
name
,
int
value
,
isc_symtab_t
*
symtab
,
const
char
*
fmt
,
isc_log_t
*
logctx
,
isc_mem_t
*
mctx
)
{
char
*
key
;
const
char
*
file
;
unsigned
int
line
;
isc_result_t
result
;
isc_symvalue_t
symvalue
;
key
=
isc_mem_strdup
(
mctx
,
name
);
if
(
key
==
NULL
)
return
(
ISC_R_NOMEMORY
);
symvalue
.
as_pointer
=
obj
;
result
=
isc_symtab_define
(
symtab
,
key
,
value
,
symvalue
,
isc_symexists_reject
);
if
(
result
==
ISC_R_EXISTS
)
{
RUNTIME_CHECK
(
isc_symtab_lookup
(
symtab
,
key
,
value
,
&
symvalue
)
==
ISC_R_SUCCESS
);
file
=
cfg_obj_file
(
symvalue
.
as_pointer
);
line
=
cfg_obj_line
(
symvalue
.
as_pointer
);
if
(
file
==
NULL
)
file
=
"<unknown file>"
;
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
fmt
,
key
,
file
,
line
);
isc_mem_free
(
mctx
,
key
);
result
=
ISC_R_EXISTS
;
}
else
if
(
result
!=
ISC_R_SUCCESS
)
{
isc_mem_free
(
mctx
,
key
);
}
return
(
result
);
}
static
isc_result_t
mustbesecure
(
cfg_obj_t
*
secure
,
isc_symtab_t
*
symtab
,
isc_log_t
*
logctx
,
isc_mem_t
*
mctx
)
...
...
@@ -290,9 +323,6 @@ mustbesecure(cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
dns_name_t
*
name
;
isc_buffer_t
b
;
isc_result_t
result
=
ISC_R_SUCCESS
;
isc_result_t
tresult
;
isc_symvalue_t
symvalue
;
char
*
key
;
dns_fixedname_init
(
&
fixed
);
name
=
dns_fixedname_name
(
&
fixed
);
...
...
@@ -300,42 +330,16 @@ mustbesecure(cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
str
=
cfg_obj_asstring
(
obj
);
isc_buffer_init
(
&
b
,
str
,
strlen
(
str
));
isc_buffer_add
(
&
b
,
strlen
(
str
));
t
result
=
dns_name_fromtext
(
name
,
&
b
,
dns_rootname
,
ISC_FALSE
,
NULL
);
if
(
t
result
!=
ISC_R_SUCCESS
)
{
result
=
dns_name_fromtext
(
name
,
&
b
,
dns_rootname
,
ISC_FALSE
,
NULL
);
if
(
result
!=
ISC_R_SUCCESS
)
{
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
"bad domain name '%s'"
,
str
);
result
=
tresult
;
}
else
{
dns_name_format
(
name
,
namebuf
,
sizeof
(
namebuf
));
key
=
isc_mem_strdup
(
mctx
,
namebuf
);
if
(
key
==
NULL
)
return
(
ISC_R_NOMEMORY
);
symvalue
.
as_pointer
=
secure
;
tresult
=
isc_symtab_define
(
symtab
,
key
,
1
,
symvalue
,
isc_symexists_reject
);
if
(
tresult
==
ISC_R_EXISTS
)
{
const
char
*
file
;
unsigned
int
line
;
RUNTIME_CHECK
(
isc_symtab_lookup
(
symtab
,
key
,
1
,
&
symvalue
)
==
ISC_R_SUCCESS
);
isc_mem_free
(
mctx
,
key
);
file
=
cfg_obj_file
(
symvalue
.
as_pointer
);
line
=
cfg_obj_line
(
symvalue
.
as_pointer
);
if
(
file
==
NULL
)
file
=
"<unknown file>"
;
cfg_obj_log
(
secure
,
logctx
,
ISC_LOG_ERROR
,
"dnssec-must-be-secure '%s': already "
"exists previous definition: %s:%u"
,
namebuf
,
file
,
line
);
result
=
tresult
;
}
else
if
(
tresult
!=
ISC_R_SUCCESS
)
{
isc_mem_free
(
mctx
,
key
);
result
=
tresult
;
}
result
=
nameexist
(
secure
,
namebuf
,
1
,
symtab
,
"dnssec-must-be-secure '%s': already "
"exists previous definition: %s:%u"
,
logctx
,
mctx
);
}
return
(
result
);
}
...
...
@@ -353,6 +357,7 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
unsigned
int
i
;
cfg_obj_t
*
obj
=
NULL
;
cfg_listelt_t
*
element
;
isc_symtab_t
*
symtab
=
NULL
;
static
intervaltable
intervals
[]
=
{
{
"cleaning-interval"
,
60
,
28
*
24
*
60
},
/* 28 days */
...
...
@@ -458,21 +463,70 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
obj
=
NULL
;
(
void
)
cfg_map_get
(
options
,
"dnssec-lookaside"
,
&
obj
);
if
(
obj
!=
NULL
)
{
dns_fixedname_t
fixedname
;
const
char
*
dlv
;
isc_buffer_t
b
;
dlv
=
cfg_obj_asstring
(
obj
);
dns_fixedname_init
(
&
fixedname
);
isc_buffer_init
(
&
b
,
dlv
,
strlen
(
dlv
));
isc_buffer_add
(
&
b
,
strlen
(
dlv
));
tresult
=
dns_name_fromtext
(
dns_fixedname_name
(
&
fixedname
),
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
);
if
(
tresult
!=
ISC_R_SUCCESS
)
{
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
"bad domain name '%s'"
,
dlv
);
tresult
=
isc_symtab_create
(
mctx
,
100
,
freekey
,
mctx
,
ISC_TRUE
,
&
symtab
);
if
(
tresult
!=
ISC_R_SUCCESS
)
result
=
tresult
;
for
(
element
=
cfg_list_first
(
obj
);
element
!=
NULL
;
element
=
cfg_list_next
(
element
))
{
dns_fixedname_t
fixedname
;
dns_name_t
*
name
;
const
char
*
dlv
;
isc_buffer_t
b
;
obj
=
cfg_listelt_value
(
element
);
dlv
=
cfg_obj_asstring
(
cfg_tuple_get
(
obj
,
"domain"
));
dns_fixedname_init
(
&
fixedname
);
name
=
dns_fixedname_name
(
&
fixedname
);
isc_buffer_init
(
&
b
,
dlv
,
strlen
(
dlv
));
isc_buffer_add
(
&
b
,
strlen
(
dlv
));
tresult
=
dns_name_fromtext
(
name
,
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
);
if
(
tresult
!=
ISC_R_SUCCESS
)
{
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
"bad domain name '%s'"
,
dlv
);
result
=
tresult
;
}
if
(
symtab
!=
NULL
)
{
tresult
=
nameexist
(
obj
,
dlv
,
1
,
symtab
,
"dnssec-lookaside '%s': "
"already exists previous "
"definition: %s:%u"
,
logctx
,
mctx
);
if
(
tresult
!=
ISC_R_SUCCESS
&&
result
==
ISC_R_SUCCESS
)
result
=
tresult
;
}
/*
* XXXMPA to be removed when multiple lookaside
* namespaces are supported.
*/
if
(
!
dns_name_equal
(
dns_rootname
,
name
))
{
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
"dnssec-lookaside '%s': "
"non-root not yet supported"
,
dlv
);
if
(
result
==
ISC_R_SUCCESS
)
result
=
ISC_R_FAILURE
;
}
dlv
=
cfg_obj_asstring
(
cfg_tuple_get
(
obj
,
"trust-anchor"
));
dns_fixedname_init
(
&
fixedname
);
isc_buffer_init
(
&
b
,
dlv
,
strlen
(
dlv
));
isc_buffer_add
(
&
b
,
strlen
(
dlv
));
tresult
=
dns_name_fromtext
(
name
,
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
);
if
(
tresult
!=
ISC_R_SUCCESS
)
{
cfg_obj_log
(
obj
,
logctx
,
ISC_LOG_ERROR
,
"bad domain name '%s'"
,
dlv
);
if
(
result
==
ISC_R_SUCCESS
)
result
=
tresult
;
}
}
if
(
symtab
!=
NULL
)
isc_symtab_destroy
(
&
symtab
);
}
/*
...
...
@@ -643,7 +697,6 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
unsigned
int
ztype
;
cfg_obj_t
*
zoptions
;
cfg_obj_t
*
obj
=
NULL
;
isc_symvalue_t
symvalue
;
isc_result_t
result
=
ISC_R_SUCCESS
;
isc_result_t
tresult
;
unsigned
int
i
;
...
...
@@ -758,48 +811,22 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
dns_fixedname_init
(
&
fixedname
);
isc_buffer_init
(
&
b
,
zname
,
strlen
(
zname
));
isc_buffer_add
(
&
b
,
strlen
(
zname
));
result
=
dns_name_fromtext
(
dns_fixedname_name
(
&
fixedname
),
&
b
,
t
result
=
dns_name_fromtext
(
dns_fixedname_name
(
&
fixedname
),
&
b
,
dns_rootname
,
ISC_TRUE
,
NULL
);
if
(
result
!=
ISC_R_SUCCESS
)
{
cfg_obj_log
(
zconfig
,
logctx
,
ISC_LOG_ERROR
,
"zone '%s': is not a valid name"
,
zname
);
result
=
ISC_R_FAILURE
;
t
result
=
ISC_R_FAILURE
;
}
else
{
char
namebuf
[
DNS_NAME_FORMATSIZE
];
char
*
key
;
dns_name_format
(
dns_fixedname_name
(
&
fixedname
),
namebuf
,
sizeof
(
namebuf
));
key
=
isc_mem_strdup
(
mctx
,
namebuf
);
if
(
key
==
NULL
)
return
(
ISC_R_NOMEMORY
);
symvalue
.
as_pointer
=
zconfig
;
tresult
=
isc_symtab_define
(
symtab
,
key
,
ztype
==
HINTZONE
?
1
:
2
,
symvalue
,
isc_symexists_reject
);
if
(
tresult
==
ISC_R_EXISTS
)
{
const
char
*
file
;
unsigned
int
line
;
RUNTIME_CHECK
(
isc_symtab_lookup
(
symtab
,
key
,
ztype
==
HINTZONE
?
1
:
2
,
&
symvalue
)
==
ISC_R_SUCCESS
);
isc_mem_free
(
mctx
,
key
);
file
=
cfg_obj_file
(
symvalue
.
as_pointer
);
line
=
cfg_obj_line
(
symvalue
.
as_pointer
);
if
(
file
==
NULL
)
file
=
"<unknown file>"
;
cfg_obj_log
(
zconfig
,
logctx
,
ISC_LOG_ERROR
,
"zone '%s': already exists "
"previous definition: %s:%u"
,
zname
,
file
,
line
);
result
=
ISC_R_FAILURE
;
}
else
if
(
tresult
!=
ISC_R_SUCCESS
)
{
isc_mem_free
(
mctx
,
key
);
return
(
tresult
);
}
tresult
=
nameexist
(
zconfig
,
namebuf
,
ztype
==
HINTZONE
?
1
:
2
,
symtab
,
"zone '%s': already exists "
"previous definition: %s:%u"
,
logctx
,
mctx
);
if
(
tresult
!=
ISC_R_SUCCESS
)
result
=
tresult
;
}
/*
...
...
lib/isccfg/namedconf.c
View file @
c315e5cf
...
...
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: namedconf.c,v 1.3
3
2004/0
4/15 23:40:27
marka Exp $ */
/* $Id: namedconf.c,v 1.3
4
2004/0
6/04 02:31:43
marka Exp $ */
#include <config.h>
...
...
@@ -658,6 +658,28 @@ static cfg_type_t cfg_type_mustbesecure = {
&
cfg_rep_tuple
,
mustbesecure_fields
};
/*
* dnssec-lookaside
*/
static
keyword_type_t
trustanchor_kw
=
{
"trust-anchor"
,
&
cfg_type_astring
};
static
cfg_type_t
cfg_type_trustanchor
=
{
"trust-anchor"
,
parse_keyvalue
,
print_keyvalue
,
doc_keyvalue
,
&
cfg_rep_string
,
&
trustanchor_kw
};
static
cfg_tuplefielddef_t
lookaside_fields
[]
=
{
{
"domain"
,
&
cfg_type_astring
,
0
},
{
"trust-anchor"
,
&
cfg_type_trustanchor
,
0
},
{
NULL
,
NULL
,
0
}
};
static
cfg_type_t
cfg_type_lookaside
=
{
"lookaside"
,
cfg_parse_tuple
,
cfg_print_tuple
,
cfg_doc_tuple
,
&
cfg_rep_tuple
,
lookaside_fields
};
/*
* Clauses that can be found within the 'view' statement,
* with defaults in the 'options' statement.
...
...
@@ -703,7 +725,7 @@ view_clauses[] = {
{
"disable-algorithms"
,
&
cfg_type_disablealgorithm
,
CFG_CLAUSEFLAG_MULTI
},
{
"dnssec-enable"
,
&
cfg_type_boolean
,
0
},
{
"dnssec-lookaside"
,
&
cfg_type_
astring
,
0
},
{
"dnssec-lookaside"
,
&
cfg_type_
lookaside
,
CFG_CLAUSEFLAG_MULTI
},
{
"dnssec-must-be-secure"
,
&
cfg_type_mustbesecure
,
CFG_CLAUSEFLAG_MULTI
},
{
NULL
,
NULL
,
0
}
...
...
@@ -1201,6 +1223,7 @@ controls_clauses[] = {
CFG_CLAUSEFLAG_MULTI
|
CFG_CLAUSEFLAG_NOTIMP
},
{
NULL
,
NULL
,
0
}
};
static
cfg_clausedef_t
*
controls_clausesets
[]
=
{
controls_clauses
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment