/* Merge signatures from userid in fkey (which is keyfile) at keypos with * userid from fring (which is ringfile) at ringpos, appending result to out. */ static int mergesigs(FILE * fkey, char *keyfile, long keypos, FILE * fring, char *ringfile, long *pringpos, FILE * out) { long ringuseridpos, ringpos; int ringpktlen, keypktlen; int status; byte ctb; int copying; word32 rstamp, kstamp, xstamp; byte keyID[KEYFRAGSIZE]; char userid[256]; /* First, copy the userid packet itself, plus any comments or ctrls */ ringuseridpos = ringpos = *pringpos; fseek(fring, ringpos, SEEK_SET); (void) readkeypacket(fring, FALSE, &ctb, NULL, userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); PascalToC(userid); ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); for (;;) { ringpos = ftell(fring); status = nextkeypacket(fring, &ctb); if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) break; ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); } fseek(fring, ringpos, SEEK_SET); /* Now, ringpos points just past userid packet and ctrl packet. */ /* Advance keypos to the analogous location. */ fseek(fkey, keypos, SEEK_SET); (void) nextkeypacket(fkey, &ctb); for (;;) { keypos = ftell(fkey); status = nextkeypacket(fkey, &ctb); if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) break; } fseek(fkey, keypos, SEEK_SET); /* Second, copy all keyfile signatures that aren't in ringfile. */ copying = FALSE; for (;;) { /* Read next sig from keyfile; see if it is in ringfile; * if it is not a signature, ignore it, * if it is absent from ringfile, copy it, * if it is present, and the timestamp is not newer, ignore it, * if present and newer, replace old with new. * Loop till hit a new key or userid in keyfile, or EOF. */ keypos = ftell(fkey); status = readkeypacket(fkey, FALSE, &ctb, (byte *) & kstamp, NULL, NULL, NULL, NULL, NULL, NULL, NULL, keyID, NULL); if (status == -3) /* unrecoverable error: bad packet length etc. */ return status; keypktlen = ftell(fkey) - keypos; if (status == -1 || is_key_ctb(ctb) || ctb == CTB_USERID) break; /* EOF or next key/userid */ if (status < 0) continue; /* bad packet, skip it */ if (is_ctb_type(ctb, CTB_SKE_TYPE)) { long sig_pos; int sig_len; /* Set copying true if signature is not in the ringfile */ copying = (getpubusersig(ringfile, ringuseridpos, keyID, (byte *) & rstamp, &sig_pos, &sig_len) < 0); if (!copying) { long save_pos = ftell(fkey); fseek(fkey, keypos + 6, SEEK_SET); fread(&kstamp, 1, SIZEOF_TIMESTAMP, fkey); fseek(fkey, save_pos, SEEK_SET); convert_byteorder((byte *) & kstamp, SIZEOF_TIMESTAMP); if (verbose) fprintf(pgpout, "ring: %lx key: %lx\n", rstamp, kstamp); if (kstamp > rstamp) { /* Update, Maybe */ char *signator; if ((signator = user_from_keyID(keyID)) == NULL) { fprintf(pgpout, LANG("Replacing signature from keyID %s on userid \"%s\"\n"), keyIDstring(keyID), LOCAL_CHARSET(userid)); /* No pubkey for KeyID, no update! */ } else { long save_keypos; long save_ringpos; long KeyIDpos; int KeyIDlen; byte sigClass; fprintf(pgpout, LANG("Verifying signature from %s\n"), LOCAL_CHARSET(signator)); fprintf(pgpout, LANG("on userid \"%s\"\n"), LOCAL_CHARSET(userid)); save_keypos = ftell(fkey); save_ringpos = ftell(fring); status = getpublickey(GPK_GIVEUP, ringfile, &KeyIDpos, &KeyIDlen, NULL, NULL, (byte *) userid, NULL, NULL); if (!status) status = check_key_sig(fring, KeyIDpos, KeyIDlen, userid, fkey, keypos, ringfile, signator, (byte *) & xstamp, &sigClass); PascalToC(userid); PascalToC(signator); if (!status) { fprintf(pgpout, LANG("Replacing signature from %s\n"), LOCAL_CHARSET(signator)); fprintf(pgpout, LANG("on userid \"%s\"\n"), LOCAL_CHARSET(userid)); sig_list_add(sig_pos); ++newsigs; copying = 1; } else fprintf(pgpout, LANG("Verification Failed\n")); fseek(fring, save_ringpos, SEEK_SET); fseek(fkey, save_keypos, SEEK_SET); } } } else { char *signator; if ((signator = user_from_keyID(keyID)) == NULL) fprintf(pgpout, LANG("New signature from keyID %s on userid \"%s\"\n"), keyIDstring(keyID), LOCAL_CHARSET(userid)); else { fprintf(pgpout, LANG("New signature from %s\n"), LOCAL_CHARSET(signator)); fprintf(pgpout, LANG("on userid \"%s\"\n"), LOCAL_CHARSET(userid)); } ++newsigs; if (batchmode) show_update(keyIDstring(mykeyID)); } } if (copying && is_ctb_type(ctb, CTB_SKE_TYPE)) { copyfilepos(fkey, out, keypktlen, keypos); if (publickey) write_trust(out, KC_SIGTRUST_UNDEFINED); } } /* Third, for all ring sig's which are not replaced, copy to output */ fseek(fring, ringpos, SEEK_SET); for (;;) { ringpos = ftell(fring); if (sig_list_find(ringpos)) { /* skip signature packet */ nextkeypacket(fring, &ctb); ringpos = ftell(fring); /* skip trust packet, if present */ if (nextkeypacket(fring, &ctb) < 0 || ctb != CTB_KEYCTRL) fseek(fring, ringpos, SEEK_SET); continue; } status = nextkeypacket(fring, &ctb); ringpktlen = ftell(fring) - ringpos; if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID) break; copyfilepos(fring, out, ringpktlen, ringpos); } /* End of loop for each sig in ringfile */ sig_list_clear(); fseek(fring, ringpos, SEEK_SET); *pringpos = ringpos; return 0; } /* mergesigs */
static int handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itfnum, const struct libusb_interface_descriptor *alt) { libusb_device_handle *devh; int res, retval; retval = -1; if (libusb_open (dev, &devh) < 0) { g_warning ("Can't open device"); goto bail; } libusb_detach_kernel_driver (devh, itfnum); res = libusb_claim_interface (devh, itfnum); if (res < 0) { g_warning ("Can't claim interface %d", itfnum); goto bail; } if (option_get_master != FALSE) { if (show_master (devh, itfnum) == FALSE) goto bail; retval = 0; } if (option_master != NULL) { if (strcmp (option_master, "auto") == 0) { g_free (option_master); option_master = get_host_bdaddr (); if (option_master == NULL) { g_warning ("Can't get bdaddr from default device"); retval = -1; goto bail; } } } else { option_master = get_host_bdaddr (); if (option_master == NULL) { g_warning ("Can't get bdaddr from default device"); retval = -1; goto bail; } } if (option_store_info != FALSE) { sdp_record_t *rec; char *device; bdaddr_t dst, src; device = get_bdaddr (devh, itfnum); if (device == NULL) { retval = -1; goto bail; } rec = record_from_string (PS3_PNP_RECORD); store_record(option_master, device, rec); write_trust(option_master, device, "[all]", TRUE); store_device_id(option_master, device, 0xffff, 0x054c, 0x0268, 0); str2ba(option_master, &src); str2ba(device, &dst); write_device_profiles(&src, &dst, ""); write_device_name(&src, &dst, "PLAYSTATION(R)3 Controller"); sdp_record_free(rec); if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) { retval = -1; goto bail; } } bail: libusb_release_interface (devh, itfnum); res = libusb_attach_kernel_driver(devh, itfnum); if (res < 0) { //FIXME sometimes the kernel tells us ENOENT, but succeeds anyway... g_warning ("Reattaching the driver failed: %d", res); } if (devh != NULL) libusb_close (devh); return retval; }
/* Merge key from fkey (which is keyfile) at keypos with key from * fring (which is ringfile) at ringpos, appending result to out. */ static int mergekeys(FILE * fkey, char *keyfile, long keypos, FILE * fring, char *ringfile, long *pringpos, FILE * out) { long ringkeypos, keykeypos, ringpos; int ringpktlen, keypktlen; int status; byte ctb; int copying; boolean ring_compromise = FALSE; byte userid[256]; /* First, copy the key packet itself, plus any comments or ctrls */ ringkeypos = ringpos = *pringpos; fseek(fring, ringpos, SEEK_SET); (void) nextkeypacket(fring, &ctb); ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); for (;;) { ringpos = ftell(fring); status = nextkeypacket(fring, &ctb); if (status < 0 || is_key_ctb(ctb) || ctb == CTB_USERID) break; if (is_ctb_type(ctb, CTB_SKE_TYPE)) ring_compromise = TRUE; /* compromise cert on keyring */ ringpktlen = ftell(fring) - ringpos; copyfilepos(fring, out, ringpktlen, ringpos); } fseek(fring, ringpos, SEEK_SET); /* Now, ringpos points just past key packet and ctrl packet. */ /* Advance keypos to the analogous location. */ fseek(fkey, keypos, SEEK_SET); keykeypos = keypos; (void) nextkeypacket(fkey, &ctb); keypktlen = ftell(fkey) - keypos; /* for check_key_sig() */ for (;;) { keypos = ftell(fkey); status = nextkeypacket(fkey, &ctb); if (status < 0 || ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) break; } if (!ring_compromise && is_ctb_type(ctb, CTB_SKE_TYPE)) { /* found a compromise cert on keyfile that is not in ringfile */ word32 timestamp; byte sig_class; int cert_pktlen; cert_pktlen = ftell(fkey) - keypos; if (check_key_sig(fkey, keykeypos, keypktlen, (char *) userid, fkey, keypos, ringfile, (char *) userid, (byte *) & timestamp, &sig_class) == 0 && sig_class == KC_SIGNATURE_BYTE) { PascalToC((char *) userid); fprintf(pgpout, LANG("Key revocation certificate from \"%s\".\n"), LOCAL_CHARSET((char *) userid)); copyfilepos(fkey, out, cert_pktlen, keypos); /* Show updates */ if (batchmode) show_key(fring, *pringpos, SHOW_CHANGE); ++newrvks; } else fprintf(pgpout, LANG("\n\007WARNING: File '%s' contains bad revocation certificate.\n"), keyfile); } fseek(fkey, keypos, SEEK_SET); /* Second, copy all keyfile userid's plus signatures that aren't * in ringfile. */ copying = FALSE; for (;;) { /* Read next userid from keyfile; see if it is in ringfile; * set copying true/false accordingly. If copying is true * and it is a userid or a signature, copy it. Loop till hit * a new key in keyfile, or EOF. */ keypos = ftell(fkey); status = readkeypacket(fkey, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (status == -3) /* unrecoverable error: bad packet length etc. */ return status; keypktlen = ftell(fkey) - keypos; if (status == -1 || is_key_ctb(ctb)) break; /* EOF or next key */ if (status < 0) continue; /* bad packet, skip it */ if (ctb == CTB_USERID) { long userid_pos; int userid_len; PascalToC((char *) userid); /* Set copying true if userid is not in the ringfile */ copying = (getpubuserid(ringfile, ringkeypos, userid, &userid_pos, &userid_len, TRUE) < 0); if (copying) { putc('\n', pgpout); fprintf(pgpout, LANG("New userid: \"%s\".\n"), LOCAL_CHARSET((char *) userid)); fprintf(pgpout, LANG("\nWill be added to the following key:\n")); show_key(fring, *pringpos, 0); fprintf(pgpout, LANG("\nAdd this userid (y/N)? ")); if (batchmode || getyesno('n')) { ++newids; /* Show an update string */ if (batchmode) { fprintf(pgpout, "\n"); show_key(fring, *pringpos, SHOW_CHANGE); } } else { copying = FALSE; } } } if (copying) { if (ctb == CTB_USERID || is_ctb_type(ctb, CTB_SKE_TYPE)) { copyfilepos(fkey, out, keypktlen, keypos); if (publickey) { if (is_ctb_type(ctb, CTB_SKE_TYPE)) write_trust(out, KC_SIGTRUST_UNDEFINED); else write_trust(out, KC_LEGIT_UNKNOWN); } } } } /* Third, for all ring userid's, if not in keyfile, copy the userid * plus its dependant signatures. */ fseek(fring, ringpos, SEEK_SET); /* Grab the keyID here */ readkeypacket(fring, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); fseek(fring, ringpos, SEEK_SET); for (;;) { ringpos = ftell(fring); status = readkeypacket(fring, FALSE, &ctb, NULL, (char *) userid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ringpktlen = ftell(fring) - ringpos; if (status == -3) return status; if (status == -1 || is_key_ctb(ctb)) break; if (ctb == CTB_USERID) { long userid_pos; int userid_len; /* See if there is a match in keyfile */ PascalToC((char *) userid); /* don't use substring match (exact_match = TRUE) */ if (getpubuserid(keyfile, keykeypos, userid, &userid_pos, &userid_len, TRUE) >= 0) { if ((status = mergesigs(fkey, keyfile, userid_pos, fring, ringfile, &ringpos, out)) < 0) return status; copying = FALSE; } else { copying = TRUE; } } if (copying) { /* Copy ringfile userid and sigs to out */ copyfilepos(fring, out, ringpktlen, ringpos); } } /* End of loop for each key in ringfile */ fseek(fring, ringpos, SEEK_SET); *pringpos = ringpos; return 0; } /* mergekeys */