+/* -------------------------------------------------------------------------- */
+pdkim_pubkey *pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record) {
+ pdkim_pubkey *pub ;
+ char *p;
+ pdkim_str *cur_tag = NULL;
+ pdkim_str *cur_val = NULL;
+ int where = PDKIM_HDR_LIMBO;
+
+ pub = malloc(sizeof(pdkim_pubkey));
+ if (pub == NULL) return NULL;
+ memset(pub,0,sizeof(pdkim_pubkey));
+
+ p = raw_record;
+
+ while (*p != '\0') {
+
+ /* Ignore FWS */
+ if ( (*p == '\r') || (*p == '\n') )
+ goto NEXT_CHAR;
+
+ if (where == PDKIM_HDR_LIMBO) {
+ /* In limbo, just wait for a tag-char to appear */
+ if (!((*p >= 'a') && (*p <= 'z')))
+ goto NEXT_CHAR;
+
+ where = PDKIM_HDR_TAG;
+ }
+
+ if (where == PDKIM_HDR_TAG) {
+ if (cur_tag == NULL)
+ cur_tag = pdkim_strnew(NULL);
+
+ if ((*p >= 'a') && (*p <= 'z'))
+ pdkim_strncat(cur_tag,p,1);
+
+ if (*p == '=') {
+ where = PDKIM_HDR_VALUE;
+ goto NEXT_CHAR;
+ }
+ }
+
+ if (where == PDKIM_HDR_VALUE) {
+ if (cur_val == NULL)
+ cur_val = pdkim_strnew(NULL);
+
+ if ( (*p == '\r') || (*p == '\n') )
+ goto NEXT_CHAR;
+
+ if (*p == ';') {
+ if (cur_tag->len > 0) {
+ pdkim_strtrim(cur_val);
+ #ifdef PDKIM_DEBUG
+ if (ctx->debug_stream)
+ fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
+ #endif
+ switch (cur_tag->str[0]) {
+ case 'v':
+ /* This tag isn't evaluated because:
+ - We only support version DKIM1.
+ - Which is the default for this value (set below)
+ - Other versions are currently not specified. */
+ break;
+ case 'h':
+ pub->hashes = strdup(cur_val->str);
+ break;
+ case 'g':
+ pub->granularity = strdup(cur_val->str);
+ break;
+ case 'n':
+ pub->notes = pdkim_decode_qp(cur_val->str);
+ break;
+ case 'p':
+ pub->key = pdkim_decode_base64(cur_val->str,&(pub->key_len));
+ break;
+ case 'k':
+ pub->hashes = strdup(cur_val->str);
+ break;
+ case 's':
+ pub->srvtype = strdup(cur_val->str);
+ break;
+ case 't':
+ if (strchr(cur_val->str,'t') != NULL) pub->testing = 1;
+ if (strchr(cur_val->str,'s') != NULL) pub->no_subdomaining = 1;
+ break;
+ default:
+ #ifdef PDKIM_DEBUG
+ if (ctx->debug_stream)
+ fprintf(ctx->debug_stream, "Unknown tag encountered\n");
+ #endif
+ break;
+ }
+ }
+ pdkim_strclear(cur_tag);
+ pdkim_strclear(cur_val);
+ where = PDKIM_HDR_LIMBO;
+ goto NEXT_CHAR;
+ }
+ else pdkim_strncat(cur_val,p,1);
+ }
+
+ NEXT_CHAR:
+ p++;
+ }
+
+ /* Set fallback defaults */
+ if (pub->version == NULL) pub->version = strdup(PDKIM_PUB_RECORD_VERSION);
+ if (pub->granularity == NULL) pub->granularity = strdup("*");
+ if (pub->keytype == NULL) pub->keytype = strdup("rsa");
+ if (pub->srvtype == NULL) pub->srvtype = strdup("*");
+
+ /* p= is required */
+ if (pub->key == NULL) {
+ pdkim_free_pubkey(pub);
+ return NULL;
+ }
+
+ return pub;
+}
+