aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/getkey.c204
1 files changed, 117 insertions, 87 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 4d747f8bc..a847d413f 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -539,104 +539,134 @@ int
classify_user_id( const char *name, u32 *keyid, byte *fprint,
const char **retstr, size_t *retlen )
{
- const char *s;
- int mode = 0;
+ const char * s;
+ int mode = 0;
+ int hexprefix = 0;
+ int hexlength;
- /* check what kind of name it is */
+ /* skip leading spaces. FIXME: what is with leading spaces? */
for(s = name; *s && isspace(*s); s++ )
;
- if( isdigit( *s ) ) { /* a keyid or a fingerprint */
- int i, j;
- char buf[9];
- if( *s == '0' && s[1] == 'x' && isxdigit(s[2]) )
- s += 2; /*kludge to allow 0x034343434 */
- for(i=0; isxdigit(s[i]); i++ )
- ;
- if( s[i] && !isspace(s[i]) ) /* not terminated by EOS or blank*/
+ switch (*s) {
+ case 0: /* empty string is an error */
return 0;
- else if( i == 8 || (i == 9 && *s == '0') ) { /* short keyid */
- if( i==9 )
- s++;
- if( keyid ) {
- keyid[0] = 0;
- keyid[1] = strtoul( s, NULL, 16 );
+
+ case '.': /* an email address, compare from end */
+ mode = 5;
+ s++;
+ break;
+
+ case '<': /* an email address */
+ mode = 3;
+ break;
+
+ case '@': /* part of an email address */
+ mode = 4;
+ s++;
+ break;
+
+ case '=': /* exact compare */
+ mode = 1;
+ s++;
+ break;
+
+ case '*': /* case insensitive substring search */
+ mode = 2;
+ s++;
+ break;
+
+ case '+': /* compare individual words */
+ mode = 6;
+ s++;
+ break;
+
+ case '#': /* local user id */
+ mode = 12;
+ s++;
+ if (keyid) {
+ if (keyid_from_lid(strtoul(s, NULL, 10), keyid))
+ keyid[0] = keyid[1] = 0;
}
- mode = 10;
- }
- else if( i == 16 || (i == 17 && *s == '0') ) { /* complete keyid */
- if( i==17 )
- s++;
- mem2str(buf, s, 9 );
- keyid[0] = strtoul( buf, NULL, 16 );
- keyid[1] = strtoul( s+8, NULL, 16 );
- mode = 11;
- }
- else if( i == 32 || ( i == 33 && *s == '0' ) ) { /* md5 fingerprint */
- if( i==33 )
- s++;
- if( fprint ) {
- memset(fprint+16, 4, 0);
- for(j=0; j < 16; j++, s+=2 ) {
- int c = hextobyte( s );
- if( c == -1 )
- return 0;
- fprint[j] = c;
+ break;
+
+ default:
+ if (s[0] == '0' && s[1] == 'x') {
+ hexprefix = 1;
+ s += 2;
+ }
+
+ hexlength = strspn(s, "0123456789abcdefABCDEF");
+
+ /* check if a hexadecimal number is terminated by EOS or blank */
+ if (hexlength && s[hexlength] && !isspace(s[hexlength])) {
+ if (hexprefix) /* a "0x" prefix without correct */
+ return 0; /* termination is an error */
+ else /* The first chars looked like */
+ hexlength = 0; /* a hex number, but really were not. */
+ }
+
+ if (hexlength == 8 || (!hexprefix && hexlength == 9 && *s == '0')){
+ /* short keyid */
+ if (hexlength == 9)
+ s++;
+ if (keyid) {
+ keyid[0] = 0;
+ keyid[1] = strtoul( s, NULL, 16 );
}
+ mode = 10;
}
- mode = 16;
- }
- else if( i == 40 || ( i == 41 && *s == '0' ) ) { /* sha1/rmd160 fprint*/
- if( i==33 )
- s++;
- if( fprint ) {
- for(j=0; j < 20; j++, s+=2 ) {
- int c = hextobyte( s );
- if( c == -1 )
- return 0;
- fprint[j] = c;
+ else if (hexlength == 16 || (!hexprefix && hexlength == 17
+ && *s == '0')) {
+ /* complete keyid */
+ char buf[9];
+ if (hexlength == 17)
+ s++;
+ mem2str(buf, s, 9 );
+ keyid[0] = strtoul( buf, NULL, 16 );
+ keyid[1] = strtoul( s+8, NULL, 16 );
+ mode = 11;
+ }
+ else if (hexlength == 32 || (!hexprefix && hexlength == 33
+ && *s == '0')) {
+ /* md5 fingerprint */
+ int i;
+ if (hexlength == 33)
+ s++;
+ if (fprint) {
+ memset(fprint+16, 4, 0);
+ for (i=0; i < 16; i++, s+=2) {
+ int c = hextobyte(s);
+ if (c == -1)
+ return 0;
+ fprint[i] = c;
+ }
}
+ mode = 16;
+ }
+ else if (hexlength == 40 || (!hexprefix && hexlength == 41
+ && *s == '0')) {
+ /* sha1/rmd160 fingerprint */
+ int i;
+ if (hexlength == 41)
+ s++;
+ if (fprint) {
+ for (i=0; i < 20; i++, s+=2) {
+ int c = hextobyte(s);
+ if (c == -1)
+ return 0;
+ fprint[i] = c;
+ }
+ }
+ mode = 20;
+ }
+ else {
+ if (hexprefix) /* This was a hex number with a prefix */
+ return 0; /* and a wrong length */
+
+ mode = 2; /* Default is case insensitive substring search */
}
- mode = 20;
- }
- else
- return 0;
- }
- else if( *s == '=' ) { /* exact search */
- mode = 1;
- s++;
- }
- else if( *s == '*' ) { /* substring search */
- mode = 2;
- s++;
- }
- else if( *s == '<' ) { /* an email address */
- mode = 3;
- }
- else if( *s == '@' ) { /* a part of an email address */
- mode = 4;
- s++;
- }
- else if( *s == '.' ) { /* an email address, compare from end */
- mode = 5;
- s++;
- }
- else if( *s == '+' ) { /* word match mode */
- mode = 6;
- s++;
- }
- else if( *s == '#' ) { /* use local id */
- mode = 12;
- s++;
- if( keyid ) {
- if( keyid_from_lid( strtoul( s, NULL, 10), keyid ) )
- keyid[0] = keyid[1] = 0;
- }
}
- else if( !*s ) /* empty string */
- return 0;
- else
- mode = 2;
if( retstr )
*retstr = s;