/** +-5-+ +---+ v | v | +------+ +------+ +------+ +------+ +------+ | 0 |--$--> |1-hdr |--alnum--> |2-data|----\r-->| 6-LF |---\n--->| done |--> 0 +------+ +------+ +------+ +------+ +------+ | ^ * +--------\r-------+ V | +------+ +------+ +------+ |3-cks |--xdigit-->|4-cks |-xdigit->| 5-CR | +------+ +------+ +------+ return to start conditions: 1. buffer overflow 2. invalid character for state checksum calculation two hex digits represent the XOR of all characters between, but not including, the "$" and "*". A checksum is required on some sentences. */ int nmeap_parse(nmeap_context_t *context,char ch) { int status = 0; /* check for input buffer overrun first to avoid duplicating code in the individual states */ if ((size_t)context->input_count >= (sizeof(context->input)-1)) { /* input buffer overrun, restart state machine */ context->input_state = 0; /* reset input count */ context->input_count = 0; } /* store the byte */ context->input[context->input_count] = ch; /* next buffer position */ context->input_count++; /* run it through the lexical scanner */ switch(context->input_state) { /* LOOKING FOR $ */ case 0: if (ch == '$') { /*look for id */ context->input_state = 1; context->ccks = 0; context->icks = 0; } else { /* header error, start over */ context->err_hdr++; context->input_state = 0; context->input_count = 0; } break; /* LOOKING FOR 5 CHARACTER SENTENCE ID */ case 1: /* allow numbers even though it isn't usually done */ /* a proprietary id might have a numeral */ if (isalnum((unsigned char)ch)) { /* store name separately */ context->input_name[context->input_count - 2] = ch; /* checksum */ context->ccks ^= ch; /* end of header? */ if (context->input_count >= 6) { /* yes, get body */ context->input_state = 2; } } else { /* bad character, start over */ context->err_id++; context->input_state = 0; context->input_count = 0; } break; /* LOOKING FOR CR OR CHECKSUM INDICATOR */ case 2: if (ch == '*') { /* this sentence has a checksum */ context->input_state = 3; } else if (ch == '\r') { /* carriage return, no checksum, force a match */ context->icks = 0; context->ccks = 0; context->input_state = 6; } else { /* continue accumulating data */ /* checksum */ context->ccks ^= ch; } break; /* LOOKING FOR FIRST CHECKSUM CHARACTER */ case 3: /* must be upper case hex digit */ if (isxdigit((unsigned char)ch) && (ch <= 'F')) { /* got first checksum byte */ context->input_state = 4; context->icks = HEXTOBIN(ch) << 4; } else { /* input error, restart */ context->err_cks++; context->input_state = 0; context->input_count = 0; } break; /* LOOKING FOR SECOND CHECKSUM CHARACTER */ case 4: /* must be upper case hex digit */ if (isxdigit((unsigned char)ch) && (ch <= 'F')) { /* got second checksum byte */ context->input_state = 5; context->icks += HEXTOBIN(ch); } else { /* input error, restart */ context->err_cks++; context->input_state = 0; context->input_count = 0; } break; /* LOOKING FOR CR */ case 5: if (ch == '\r') { /* carriage return */ context->input_state = 6; } else { /* input error, restart */ context->err_crl++; context->input_state = 0; context->input_count = 0; } break; /* LOOKING FOR LINE FEED */ case 6: if (ch == '\n') { /* linefeed, line complete */ /* delimit buffer */ context->input[context->input_count] = 0; /* if the checksums match, process the sentence */ if (context->ccks == context->icks) { /* process */ status = nmeap_process(context); /* count good messages */ context->msgs++; } else { /* count checksum errors */ context->err_cks++; } /* restart next time */ context->input_state = 0; context->input_count = 0; } else { /* input error, restart */ context->err_crl++; context->input_state = 0; context->input_count = 0; } break; default: context->err_unk++; context->input_state = 0; break; } return status; }
void import_ownertrust (ctrl_t ctrl, const char *fname ) { estream_t fp; int is_stdin=0; char line[256]; char *p; size_t n, fprlen; unsigned int otrust; byte fpr[MAX_FINGERPRINT_LEN]; int any = 0; int rc; init_trustdb (ctrl, 0); if( iobuf_is_pipe_filename (fname) ) { fp = es_stdin; fname = "[stdin]"; is_stdin = 1; } else if( !(fp = es_fopen( fname, "r" )) ) { log_error ( _("can't open '%s': %s\n"), fname, strerror(errno) ); return; } if (is_secured_file (es_fileno (fp))) { es_fclose (fp); gpg_err_set_errno (EPERM); log_error (_("can't open '%s': %s\n"), fname, strerror(errno) ); return; } while (es_fgets (line, DIM(line)-1, fp)) { TRUSTREC rec; if( !*line || *line == '#' ) continue; n = strlen(line); if( line[n-1] != '\n' ) { log_error (_("error in '%s': %s\n"), fname, _("line too long") ); /* ... or last line does not have a LF */ break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) if( !hexdigitp(p) ) break; if( *p != ':' ) { log_error (_("error in '%s': %s\n"), fname, _("colon missing") ); continue; } fprlen = p - line; if( fprlen != 32 && fprlen != 40 && fprlen != 64) { log_error (_("error in '%s': %s\n"), fname, _("invalid fingerprint") ); continue; } if( sscanf(p, ":%u:", &otrust ) != 1 ) { log_error (_("error in '%s': %s\n"), fname, _("ownertrust value missing")); continue; } if( !otrust ) continue; /* no otrust defined - no need to update or insert */ /* Convert the ascii fingerprint to binary */ for(p=line, fprlen=0; fprlen < MAX_FINGERPRINT_LEN && *p != ':'; p += 2 ) fpr[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]); while (fprlen < MAX_FINGERPRINT_LEN) fpr[fprlen++] = 0; rc = tdbio_search_trust_byfpr (fpr, &rec); if( !rc ) { /* found: update */ if (rec.r.trust.ownertrust != otrust) { if (!opt.quiet) { if( rec.r.trust.ownertrust ) log_info("changing ownertrust from %u to %u\n", rec.r.trust.ownertrust, otrust ); else log_info("setting ownertrust to %u\n", otrust ); } rec.r.trust.ownertrust = otrust; write_record (ctrl, &rec); any = 1; } } else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) { /* insert */ if (!opt.quiet) log_info("inserting ownertrust of %u\n", otrust ); memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (ctrl); rec.rectype = RECTYPE_TRUST; memcpy (rec.r.trust.fingerprint, fpr, 20); rec.r.trust.ownertrust = otrust; write_record (ctrl, &rec); any = 1; } else /* error */ log_error (_("error finding trust record in '%s': %s\n"), fname, gpg_strerror (rc)); } if (es_ferror (fp)) log_error ( _("read error in '%s': %s\n"), fname, strerror(errno) ); if (!is_stdin) es_fclose (fp); if (any) { revalidation_mark (ctrl); rc = tdbio_sync (); if (rc) log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); } }