mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 02:38:09 +09:00
Add more error checks to signature_from_string().
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@538 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
196
libssh/keys.c
196
libssh/keys.c
@@ -849,141 +849,207 @@ static STRING *signature_to_string(SIGNATURE *sign) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO : split this function in two so it becomes smaller */
|
/* TODO : split this function in two so it becomes smaller */
|
||||||
SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature,PUBLIC_KEY *pubkey,int needed_type){
|
SIGNATURE *signature_from_string(SSH_SESSION *session, STRING *signature,
|
||||||
|
PUBLIC_KEY *pubkey, int needed_type) {
|
||||||
|
SIGNATURE *sign = NULL;
|
||||||
|
BUFFER *tmpbuf = NULL;
|
||||||
|
STRING *rs = NULL;
|
||||||
|
STRING *type_s = NULL;
|
||||||
|
STRING *e = NULL;
|
||||||
|
char *type = NULL;
|
||||||
|
int len;
|
||||||
|
int rsalen;
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_t sig;
|
gcry_sexp_t sig;
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
DSA_SIG *sig;
|
DSA_SIG *sig = NULL;
|
||||||
STRING *r,*s;
|
STRING *r = NULL;
|
||||||
|
STRING *s = NULL;
|
||||||
#endif
|
#endif
|
||||||
SIGNATURE *sign;
|
|
||||||
BUFFER *tmpbuf;
|
|
||||||
STRING *rs;
|
|
||||||
STRING *type_s,*e;
|
|
||||||
int len,rsalen;
|
|
||||||
char *type;
|
|
||||||
|
|
||||||
sign = malloc(sizeof(SIGNATURE));
|
sign = malloc(sizeof(SIGNATURE));
|
||||||
if (sign == NULL) {
|
if (sign == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL, "No space left");
|
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpbuf = buffer_new();
|
tmpbuf = buffer_new();
|
||||||
if (tmpbuf == NULL) {
|
if (tmpbuf == NULL) {
|
||||||
ssh_set_error(session, SSH_FATAL, "No space left");
|
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_add_data(tmpbuf,signature->string,string_len(signature));
|
if (buffer_add_data(tmpbuf, signature->string, string_len(signature)) < 0) {
|
||||||
type_s=buffer_get_ssh_string(tmpbuf);
|
|
||||||
if(!type_s){
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid signature packet");
|
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
type=string_to_char(type_s);
|
|
||||||
free(type_s);
|
type_s = buffer_get_ssh_string(tmpbuf);
|
||||||
switch(needed_type){
|
if (type_s == NULL) {
|
||||||
case TYPE_DSS:
|
ssh_set_error(session, SSH_FATAL, "Invalid signature packet");
|
||||||
if(strcmp(type,"ssh-dss")){
|
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type);
|
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
free(type);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = string_to_char(type_s);
|
||||||
|
free(type_s);
|
||||||
|
if (type == NULL) {
|
||||||
|
signature_free(sign);
|
||||||
|
buffer_free(tmpbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(needed_type) {
|
||||||
|
case TYPE_DSS:
|
||||||
|
if (strcmp(type, "ssh-dss") != 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", type);
|
||||||
|
signature_free(sign);
|
||||||
|
buffer_free(tmpbuf);
|
||||||
|
SAFE_FREE(type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_RSA:
|
case TYPE_RSA:
|
||||||
if(strcmp(type,"ssh-rsa")){
|
if (strcmp(type, "ssh-rsa")) {
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type);
|
ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", type);
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
free(type);
|
SAFE_FREE(type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session,SSH_FATAL,"Invalid signature type : %s",type);
|
ssh_set_error(session, SSH_FATAL, "Invalid signature type: %s", type);
|
||||||
free(type);
|
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
|
SAFE_FREE(type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
free(type);
|
SAFE_FREE(type);
|
||||||
switch(needed_type){
|
|
||||||
|
switch(needed_type) {
|
||||||
case TYPE_DSS:
|
case TYPE_DSS:
|
||||||
rs=buffer_get_ssh_string(tmpbuf);
|
rs = buffer_get_ssh_string(tmpbuf);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
if(!rs || string_len(rs)!=40){ /* 40 is the dual signature blob len. */
|
|
||||||
if(rs)
|
/* 40 is the dual signature blob len. */
|
||||||
free(rs);
|
if (rs == NULL || string_len(rs) != 40) {
|
||||||
|
string_free(rs);
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* we make use of strings (because we have all-made functions to convert them to bignums (ou pas ;)*/
|
|
||||||
|
/* we make use of strings (because we have all-made functions to convert
|
||||||
|
* them to bignums (ou pas ;) */
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_build(&sig,NULL,"(sig-val(dsa(r %b)(s %b)))",20,rs->string,20,rs->string+20);
|
if (gcry_sexp_build(&sig, NULL, "(sig-val(dsa(r %b)(s %b)))",
|
||||||
|
20 ,rs->string, 20, rs->string + 20)) {
|
||||||
|
string_free(rs);
|
||||||
|
signature_free(sign);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
r=string_new(20);
|
r = string_new(20);
|
||||||
s=string_new(20);
|
s = string_new(20);
|
||||||
string_fill(r,rs->string,20);
|
if (r == NULL || s == NULL) {
|
||||||
string_fill(s,rs->string+20,20);
|
string_free(r);
|
||||||
sig=DSA_SIG_new();
|
string_free(s);
|
||||||
sig->r=make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */
|
string_free(rs);
|
||||||
sig->s=make_string_bn(s);
|
signature_free(sign);
|
||||||
free(r);
|
return NULL;
|
||||||
free(s);
|
}
|
||||||
|
|
||||||
|
string_fill(r, rs->string, 20);
|
||||||
|
string_fill(s, rs->string + 20, 20);
|
||||||
|
|
||||||
|
sig = DSA_SIG_new();
|
||||||
|
if (sig == NULL) {
|
||||||
|
string_free(r);
|
||||||
|
string_free(s);
|
||||||
|
string_free(rs);
|
||||||
|
signature_free(sign);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sig->r = make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */
|
||||||
|
sig->s = make_string_bn(s);
|
||||||
|
string_free(r);
|
||||||
|
string_free(s);
|
||||||
|
|
||||||
|
if (sig->r == NULL || sig->s == NULL) {
|
||||||
|
string_free(rs);
|
||||||
|
DSA_SIG_free(sig);
|
||||||
|
signature_free(sign);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("r",rs->string,20);
|
ssh_print_hexa("r", rs->string, 20);
|
||||||
ssh_print_hexa("s",rs->string+20,20);
|
ssh_print_hexa("s", rs->string + 20, 20);
|
||||||
#endif
|
#endif
|
||||||
free(rs);
|
string_free(rs);
|
||||||
sign->type=TYPE_DSS;
|
|
||||||
sign->dsa_sign=sig;
|
sign->type = TYPE_DSS;
|
||||||
|
sign->dsa_sign = sig;
|
||||||
|
|
||||||
return sign;
|
return sign;
|
||||||
case TYPE_RSA:
|
case TYPE_RSA:
|
||||||
e=buffer_get_ssh_string(tmpbuf);
|
e = buffer_get_ssh_string(tmpbuf);
|
||||||
buffer_free(tmpbuf);
|
buffer_free(tmpbuf);
|
||||||
if(e == NULL) {
|
if (e == NULL) {
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
len=string_len(e);
|
len = string_len(e);
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
rsalen=(gcry_pk_get_nbits(pubkey->rsa_pub)+7)/8;
|
rsalen = (gcry_pk_get_nbits(pubkey->rsa_pub) + 7) / 8;
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
rsalen=RSA_size(pubkey->rsa_pub);
|
rsalen = RSA_size(pubkey->rsa_pub);
|
||||||
#endif
|
#endif
|
||||||
if(len>rsalen){
|
if (len > rsalen) {
|
||||||
free(e);
|
string_free(e);
|
||||||
signature_free(sign);
|
signature_free(sign);
|
||||||
ssh_set_error(session,SSH_FATAL,"signature too big ! %d instead of %d",len,rsalen);
|
ssh_set_error(session, SSH_FATAL, "Signature too big! %d instead of %d",
|
||||||
|
len, rsalen);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(len<rsalen)
|
|
||||||
ssh_log(session,SSH_LOG_RARE,"RSA signature len %d < %d",len,rsalen);
|
if (len < rsalen) {
|
||||||
sign->type=TYPE_RSA;
|
ssh_log(session, SSH_LOG_RARE, "RSA signature len %d < %d",
|
||||||
|
len, rsalen);
|
||||||
|
}
|
||||||
|
sign->type = TYPE_RSA;
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_build(&sig,NULL,"(sig-val(rsa(s %b)))",string_len(e),e->string);
|
if (gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))",
|
||||||
sign->rsa_sign=sig;
|
string_len(e), e->string)) {
|
||||||
|
signature_free(sign);
|
||||||
|
string_free(e);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sign->rsa_sign = sig;
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
sign->rsa_sign=e;
|
sign->rsa_sign = e;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
|
ssh_log(session, SSH_LOG_FUNCTIONS, "len e: %d", len);
|
||||||
ssh_print_hexa("rsa signature", e->string, len);
|
ssh_print_hexa("RSA signature", e->string, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
free(e);
|
string_free(e);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return sign;
|
return sign;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void signature_free(SIGNATURE *sign) {
|
void signature_free(SIGNATURE *sign) {
|
||||||
|
|||||||
Reference in New Issue
Block a user