Changeset 758 in openpam
- Timestamp:
- Jan 23, 2014, 8:19:54 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/security/Makefile.am
r706 r758 16 16 oath.h \ 17 17 oath_constants.h \ 18 oath_rfc3986.h \ 18 19 oath_rfc4648.h \ 19 20 oath_types.h -
trunk/include/security/oath.h
r752 r758 1 1 /*- 2 * Copyright (c) 2012-2013 Universitetet i Oslo 2 * Copyright (c) 2012-2014 Universitetet i Oslo 3 * Copyright (c) 2013-2014 Dag-Erling Smørgrav 3 4 * All rights reserved. 4 5 * … … 35 36 #include <security/oath_constants.h> 36 37 #include <security/oath_types.h> 38 #include <security/oath_rfc3986.h> 37 39 #include <security/oath_rfc4648.h> 38 40 -
trunk/lib/liboath/Makefile.am
r752 r758 13 13 oath_key_create.c \ 14 14 oath_key_dummy.c \ 15 oath_key_from_uri.c \ 15 16 oath_key_free.c \ 16 oath_key.c 17 oath_key.c \ 18 oath_uri_decode.c 17 19 18 20 liboath_la_LDFLAGS = -no-undefined -version-info @LIB_MAJ@ -
trunk/lib/liboath/oath_key.c
r730 r758 36 36 #include <sys/types.h> 37 37 38 #include <errno.h>39 38 #include <inttypes.h> 40 #include <limits.h>41 39 #include <stdio.h> 42 40 #include <stdlib.h> 43 #include <string.h>44 41 45 42 #include <security/pam_appl.h> 46 43 #include <security/openpam.h> 47 44 48 #include "openpam_asprintf.h"49 45 #include "openpam_strlcmp.h" 50 46 51 47 #include <security/oath.h> 52 53 /*54 * Allocate a struct oath_key and populate it from a Google Authenticator55 * otpauth URI56 */57 struct oath_key *58 oath_key_from_uri(const char *uri)59 {60 struct oath_key *key;61 const char *p, *q, *r;62 uintmax_t n;63 char *e;64 65 if ((key = oath_key_alloc()) == NULL)66 return (NULL);67 68 /* check method */69 p = uri;70 if (strlcmp("otpauth://", p, 10) != 0)71 goto invalid;72 p += 10;73 74 /* check mode (hotp = event, totp = time-sync) */75 if ((q = strchr(p, '/')) == NULL)76 goto invalid;77 if (strlcmp("hotp", p, q - p) == 0) {78 key->mode = om_hotp;79 } else if (strlcmp("totp", p, q - p) == 0) {80 key->mode = om_totp;81 } else {82 goto invalid;83 }84 p = q + 1;85 86 /* extract label */87 /* XXX actually URI-encoded */88 if ((q = strchr(p, '?')) == NULL)89 goto invalid;90 if ((key->labellen = q - p + 1) > sizeof key->label)91 goto invalid;92 memcpy(key->label, p, q - p);93 key->label[q - p] = '\0';94 p = q + 1;95 96 /* extract parameters */97 key->counter = UINT64_MAX;98 key->lastused = UINT64_MAX;99 while (*p != '\0') {100 if ((q = strchr(p, '=')) == NULL)101 goto invalid;102 q = q + 1;103 if ((r = strchr(p, '&')) == NULL)104 r = strchr(p, '\0');105 if (r < q)106 /* & before = */107 goto invalid;108 /* p points to key, q points to value, r points to & or NUL */109 if (strlcmp("secret=", p, q - p) == 0) {110 if (key->keylen != 0)111 /* dupe */112 goto invalid;113 key->keylen = sizeof key->key;114 if (base32_dec(q, r - q, key->key, &key->keylen) != 0)115 goto invalid;116 if (base32_enclen(key->keylen) != (size_t)(r - q))117 goto invalid;118 } else if (strlcmp("algorithm=", p, q - p) == 0) {119 if (key->hash != oh_undef)120 /* dupe */121 goto invalid;122 if (strlcmp("SHA1", q, r - q) == 0)123 key->hash = oh_sha1;124 else if (strlcmp("SHA256", q, r - q) == 0)125 key->hash = oh_sha256;126 else if (strlcmp("SHA512", q, r - q) == 0)127 key->hash = oh_sha512;128 else if (strlcmp("MD5", q, r - q) == 0)129 key->hash = oh_md5;130 else131 goto invalid;132 } else if (strlcmp("digits=", p, q - p) == 0) {133 if (key->digits != 0)134 /* dupe */135 goto invalid;136 /* only 6 or 8 */137 if (r - q != 1 || (*q != '6' && *q != '8'))138 goto invalid;139 key->digits = *q - '0';140 } else if (strlcmp("counter=", p, q - p) == 0) {141 if (key->counter != UINT64_MAX)142 /* dupe */143 goto invalid;144 n = strtoumax(q, &e, 10);145 if (e != r || n >= UINT64_MAX)146 goto invalid;147 key->counter = (uint64_t)n;148 } else if (strlcmp("lastused=", p, q - p) == 0) {149 if (key->lastused != UINT64_MAX)150 /* dupe */151 goto invalid;152 n = strtoumax(q, &e, 10);153 if (e != r || n >= UINT64_MAX)154 goto invalid;155 key->lastused = (uint64_t)n;156 } else if (strlcmp("period=", p, q - p) == 0) {157 if (key->timestep != 0)158 /* dupe */159 goto invalid;160 n = strtoumax(q, &e, 10);161 if (e != r || n > OATH_MAX_TIMESTEP)162 goto invalid;163 key->timestep = n;164 } else {165 goto invalid;166 }167 /* final parameter? */168 if (*r == '\0')169 break;170 /* skip & and continue */171 p = r + 1;172 }173 174 /* sanity checks and default values */175 if (key->mode == om_hotp) {176 if (key->counter == UINT64_MAX)177 key->counter = 0;178 if (key->timestep != 0)179 goto invalid;180 if (key->lastused != UINT64_MAX)181 goto invalid;182 } else if (key->mode == om_totp) {183 if (key->counter != UINT64_MAX)184 goto invalid;185 if (key->timestep == 0)186 key->timestep = OATH_DEF_TIMESTEP;187 if (key->lastused == UINT64_MAX)188 key->lastused = 0;189 } else {190 /* unreachable */191 oath_key_free(key);192 return (NULL);193 }194 if (key->hash == oh_undef)195 key->hash = oh_sha1;196 if (key->digits == 0)197 key->digits = 6;198 if (key->keylen == 0)199 goto invalid;200 return (key);201 202 invalid:203 openpam_log(PAM_LOG_NOTICE, "invalid OATH URI: %s", uri);204 oath_key_free(key);205 return (NULL);206 }207 48 208 49 struct oath_key * -
trunk/lib/liboath/oath_key_from_uri.c
r756 r758 1 1 /*- 2 * Copyright (c) 2013 Universitetet i Oslo2 * Copyright (c) 2013-2014 Universitetet i Oslo 3 3 * All rights reserved. 4 4 * … … 36 36 #include <sys/types.h> 37 37 38 #include <errno.h>39 38 #include <inttypes.h> 40 #include <limits.h>41 #include <stdio.h>42 #include <stdlib.h>43 39 #include <string.h> 44 40 … … 46 42 #include <security/openpam.h> 47 43 48 #include "openpam_asprintf.h"49 44 #include "openpam_strlcmp.h" 50 45 … … 52 47 53 48 /* 54 * Allocate a struct oath_key and populate it from a Google Authenticator 55 * otpauth URI 49 * OATH 50 * 51 * Creates an OATH key from a Google otpauth URI 56 52 */ 53 57 54 struct oath_key * 58 55 oath_key_from_uri(const char *uri) … … 85 82 86 83 /* extract label */ 87 /* XXX actually URI-encoded */88 84 if ((q = strchr(p, '?')) == NULL) 89 85 goto invalid; 90 if ((key->labellen = q - p + 1) > sizeof key->label)91 goto invalid;92 memcpy(key->label, p, q - p);93 key->label[q - p] = '\0';86 key->labellen = oath_uri_decode(p, q - p, key->label, 87 sizeof key->label); 88 if (key->labellen > sizeof key->label) 89 goto invalid; 94 90 p = q + 1; 95 91 … … 206 202 } 207 203 208 struct oath_key * 209 oath_key_from_file(const char *filename) 210 { 211 struct oath_key *key; 212 FILE *f; 213 char *line; 214 size_t len; 215 216 if ((f = fopen(filename, "r")) == NULL) 217 return (NULL); 218 /* get first non-empty non-comment line */ 219 line = openpam_readline(f, NULL, &len); 220 if (strlcmp("otpauth://", line, len) == 0) { 221 key = oath_key_from_uri(line); 222 } else { 223 openpam_log(PAM_LOG_ERROR, 224 "unrecognized key file format: %s", filename); 225 key = NULL; 226 } 227 fclose(f); 228 return (key); 229 } 230 231 char * 232 oath_key_to_uri(const struct oath_key *key) 233 { 234 const char *hash; 235 char *tmp, *uri; 236 size_t kslen, urilen; 237 238 switch (key->hash) { 239 case oh_sha1: 240 hash = "SHA1"; 241 break; 242 case oh_sha256: 243 hash = "SHA256"; 244 break; 245 case oh_sha512: 246 hash = "SHA512"; 247 break; 248 case oh_md5: 249 hash = "MD5"; 250 break; 251 default: 252 return (NULL); 253 } 254 255 /* XXX the label should be URI-encoded */ 256 if (key->mode == om_hotp) { 257 urilen = asprintf(&uri, "otpauth://%s/%s?" 258 "algorithm=%s&digits=%d&counter=%ju&secret=", 259 "hotp", key->label, hash, key->digits, 260 (uintmax_t)key->counter); 261 } else if (key->mode == om_totp) { 262 urilen = asprintf(&uri, "otpauth://%s/%s?" 263 "algorithm=%s&digits=%d&period=%u&lastused=%ju&secret=", 264 "totp", key->label, hash, key->digits, key->timestep, 265 (uintmax_t)key->lastused); 266 } else { 267 /* unreachable */ 268 return (NULL); 269 } 270 271 /* compute length of base32-encoded key and append it */ 272 kslen = base32_enclen(key->keylen) + 1; 273 if ((tmp = realloc(uri, urilen + kslen)) == NULL) { 274 free(uri); 275 return (NULL); 276 } 277 uri = tmp; 278 if (base32_enc(key->key, key->keylen, uri + urilen, &kslen) != 0) { 279 free(uri); 280 return (NULL); 281 } 282 283 return (uri); 284 } 204 /** 205 * The =oath_key_from_uri parses a Google otpauth URI into a key 206 * structure. 207 * 208 * The =uri parameter points to a NUL-terminated string containing the 209 * URI. 210 * 211 * Keys created with =oath_key_from_uri must be freed using 212 * =oath_key_free. 213 * 214 * >oath_key_alloc 215 * >oath_key_free 216 * >oath_key_to_uri 217 * 218 * REFERENCES 219 * 220 * https://code.google.com/p/google-authenticator/wiki/KeyUriFormat 221 * 222 * AUTHOR UIO 223 */
Note: See TracChangeset
for help on using the changeset viewer.