int ocr_request(ocr_t *ocr, unsigned long addr, frame_geometry_t *g, int inverse, ocr_reply_t *reply, void *data) { char buf[80]; int size; /* Set data reporting callback */ ocr->ctx.reply_func = reply; ocr->ctx.reply_data = data; /* Construct request message */ size = snprintf(buf, sizeof(buf), "id=%lX geometry=%s%s\n", addr, frame_geometry_str(g), inverse ? " inv":""); dprintf("WRITE '%s'", buf); return agent_request(ocr->agent, buf, size); }
static int call_passkey_agent(DBusConnection *conn, struct passkey_agent *agent, int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba) { struct pending_agent_request *req; if (!agent) { debug("call_passkey_agent(): no agent available"); goto send; } debug("Calling PasskeyAgent.Request: name=%s, path=%s", agent->name, agent->path); req = g_new0(struct pending_agent_request, 1); req->dev = dev; bacpy(&req->sba, sba); bacpy(&req->bda, dba); req->agent = agent; req->path = g_strdup(path); req->call = agent_request(path, dba, agent, FALSE, 0); if (!req->call) goto failed; dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL); agent->pending_requests = g_slist_append(agent->pending_requests, req); return 0; failed: g_free(req->path); g_free(req); send: hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, dba); return -1; }
const unsigned char *sftp_agent_sign_data(pool *p, const char *agent_path, const unsigned char *key_data, uint32_t key_datalen, const unsigned char *data, uint32_t datalen, uint32_t *sig_datalen) { int fd; unsigned char *buf, *req, *resp, *sig_data; uint32_t buflen, flags, reqlen, reqsz, resplen; char resp_status; fd = agent_connect(agent_path); if (fd < 0) { return NULL; } /* XXX When to set flags to OLD_SIGNATURE? */ flags = 0; /* Write out the request for signing the given data. */ reqsz = buflen = 1 + key_datalen + 4 + datalen + 4 + 4; req = buf = palloc(p, reqsz); sftp_msg_write_byte(&buf, &buflen, SFTP_SSH_AGENT_REQ_SIGN_DATA); sftp_msg_write_data(&buf, &buflen, key_data, key_datalen, TRUE); sftp_msg_write_data(&buf, &buflen, data, datalen, TRUE); sftp_msg_write_int(&buf, &buflen, flags); reqlen = reqsz - buflen; resp = agent_request(p, fd, agent_path, req, reqlen, &resplen); if (resp == NULL) { int xerrno = errno; (void) close(fd); errno = xerrno; return NULL; } (void) close(fd); /* Read the response from the agent. */ resp_status = sftp_msg_read_byte(p, &resp, &resplen); if (agent_failure(resp_status) == TRUE) { pr_trace_msg(trace_channel, 5, "SSH agent at '%s' indicated failure (%d) for data signing request", agent_path, resp_status); errno = EPERM; return NULL; } if (resp_status != SFTP_SSH_AGENT_RESP_SIGN_DATA) { pr_trace_msg(trace_channel, 5, "unknown response type %d from SSH agent at '%s'", resp_status, agent_path); errno = EACCES; return NULL; } *sig_datalen = sftp_msg_read_int(p, &resp, &resplen); sig_data = sftp_msg_read_data(p, &resp, &resplen, *sig_datalen); return sig_data; }
int sftp_agent_get_keys(pool *p, const char *agent_path, array_header *key_list) { register unsigned int i; int fd; unsigned char *buf, *req, *resp; uint32_t buflen, key_count, reqlen, reqsz, resplen; char resp_status; fd = agent_connect(agent_path); if (fd < 0) { return -1; } /* Write out the request for the identities (i.e. the public keys). */ reqsz = buflen = 64; req = buf = palloc(p, reqsz); sftp_msg_write_byte(&buf, &buflen, SFTP_SSH_AGENT_REQ_IDS); reqlen = reqsz - buflen; resp = agent_request(p, fd, agent_path, req, reqlen, &resplen); if (resp == NULL) { int xerrno = errno; (void) close(fd); errno = xerrno; return -1; } (void) close(fd); /* Read the response from the agent. */ resp_status = sftp_msg_read_byte(p, &resp, &resplen); if (agent_failure(resp_status) == TRUE) { pr_trace_msg(trace_channel, 5, "SSH agent at '%s' indicated failure (%d) for identities request", agent_path, resp_status); errno = EPERM; return -1; } if (resp_status != SFTP_SSH_AGENT_RESP_IDS) { pr_trace_msg(trace_channel, 5, "unknown response type %d from SSH agent at '%s'", resp_status, agent_path); errno = EACCES; return -1; } key_count = sftp_msg_read_int(p, &resp, &resplen); if (key_count > AGENT_MAX_KEYS) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "SSH agent at '%s' returned too many keys (%lu, max %lu)", agent_path, (unsigned long) key_count, (unsigned long) AGENT_MAX_KEYS); errno = EPERM; return -1; } for (i = 0; i < key_count; i++) { unsigned char *key_data; uint32_t key_datalen; char *key_comment; struct agent_key *key; key_datalen = sftp_msg_read_int(p, &resp, &resplen); key_data = sftp_msg_read_data(p, &resp, &resplen, key_datalen); key_comment = sftp_msg_read_string(p, &resp, &resplen); if (key_comment != NULL) { pr_trace_msg(trace_channel, 9, "SSH agent at '%s' provided comment '%s' for key #%u", agent_path, key_comment, (i + 1)); } key = pcalloc(p, sizeof(struct agent_key)); key->key_data = key_data; key->key_datalen = key_datalen; key->agent_path = pstrdup(p, agent_path); *((struct agent_key **) push_array(key_list)) = key; } pr_trace_msg(trace_channel, 9, "SSH agent at '%s' provided %lu %s", agent_path, (unsigned long) key_count, key_count != 1 ? "keys" : "key"); return 0; }
main(int argc, char *argv[]) { char *pgm, *s; int ok, help; char *server; int id, nc; int i; char me[256]; char logstr[200]; pgm = argv[0]; /* Get and save our original working directory */ if (!GetWD(SelfWD, sizeof(SelfWD))) { fprintf(stderr, "%s: couldn't get working directory\n", pgm); perror(pgm); exit(4); } /* Get our own name and any path prefix */ if (pgm = strrchr(argv[0], '/')) { *pgm++ = '\0'; if (*argv[0] == '/') strcpy(Logdir, argv[0]); else make_path(Logdir, SelfWD, argv[0]); if (Verbose) printf("Logdir search is \"%s\"\n", Logdir); } else { strcpy(Logdir, SelfWD); pgm = argv[0]; } ++argv; --argc; /* See if we are running as the LOGGER */ sprintf(logstr, "{%s,%s%s}", LOGGEREXEC, LOGGEREXEC, LOGGEREXT); if (strmatch(logstr, pgm)) logger(pgm, argc, argv); /* Default options */ ok = 1; help = 0; /* Parse out command line options */ while (argc && *argv[0] == '-') { char *opt; opt = argv[0] + 1; ++argv; --argc; if (substr(opt, "help")) ++help; else if (substr(opt, "debug")) ++Debug; else if (substr(opt, "nodebug")) Debug = 0; else if (substr(opt, "verbose")) Verbose = 1; else if (substr(opt, "quiet")) Verbose = 0; else if (streq(opt, "bin") || streq(opt, "dir")) { if (argc < 1) { fprintf(stderr, "%s: missing argument to -%s\n", pgm, opt); ok = 0; break; } RootPath = argv[0]; ++argv; --argc; } else if (streq(opt, "wd") || streq(opt, "cd")) { if (argc < 1) { fprintf(stderr, "%s: missing argument to -%s\n", pgm, opt); ok = 0; break; } WorkDir = argv[0]; ++argv; --argc; } else if (substr(opt, "logger")) { if (argc < 1) { fprintf(stderr, "%s: missing argument to -%s\n", pgm, opt); ok = 0; break; } if (argv[0][0] == '/') strcpy(Logger, argv[0]); else { int len; char *name; /* Copy the current working directory */ strcpy(Logger, SelfWD); len = strlen(Logger); if (Logger[len-1] != '/') Logger[len++] = '/'; name = argv[0]; if (substr("./", name)) name += 2; strcpy(Logger+len, name); } ++argv; --argc; } else { fprintf(stderr, "%s: ignoring argument -%s\n", pgm, opt); help = 1; ok = 0; } } if (!ok || argc == 0) { usage(pgm, help); exit(!help); } server = argv[0]; ++argv; --argc; /* Allow directory to be specified as last command line arg */ if (argc) { if (RootPath) { if (!streq(RootPath, argv[0])) { fprintf(stderr, "%s: can't use -dir (%s) and specify path (%s)\n", pgm, RootPath, argv[0]); exit(4); } } else { RootPath = argv[0]; ++argv; --argc; } } /* Check for any extraneous args */ if (argc) { fprintf(stderr, "%s: too many arguments starting with \"%s\"\n", pgm, argv[0]); usage(pgm, help); exit(!help); } /* Now change to our root directory */ if (RootPath) { if (chdir(RootPath) != SYS_OK) { fprintf(stderr, "%s: couldn't chdir to \"%s\"\n", pgm, RootPath); exit(4); } } else fprintf(stderr, "%s: WARNING! no root directory specified - using .\n", pgm); /* Set up path to working directory for lauched agents */ if (WorkDir) if (*WorkDir == '/') strcpy(WorkPath, WorkDir); else make_path(WorkPath, SelfWD, WorkDir); /* Open the executable directory to process queries */ if (!GetWD(ExecPath, sizeof(ExecPath))) { fprintf(stderr, "%s: couldn't get working directory\n", pgm); perror(pgm); exit(4); } ExecDir = opendir(ExecPath); if (!ExecDir) { fprintf(stderr, "%s: couldn't open working directory \"%s\"\n", pgm, ExecPath); perror(pgm); exit(4); } #ifdef win32 /* * On windows we need to run the logger as a separate helper app * since the cygwin implementation of fork is not quite right. * Look for it in standard places as well as looking as users $PATH */ if (!Logger[0] && !find_logger()) { fprintf(stderr, "%s: couldn't find initiator \"%s\"\n", pgm, LOGGEREXEC); exit(4); } if (Verbose) printf("Logger exec is \"%s\"\n", Logger); #endif /* Make sure we found the file and it is executable */ if (Logger[0] && access(Logger, X_OK) != SYS_OK) { fprintf(stderr, "%s: initiator \"%s\" not %s\n", pgm, Logger, access(Logger, F_OK)?"found":"executable"); exit(4); } /* Deal with signals */ siginit(); /* local initialization */ event_verbose(Verbose); event_tunnel_enable(0); agentd_init(); /* Connect to our event server */ id = event_join(server, &nc); if (!id) { fprintf(stderr, "%s: couldn't join server \"%s\"\n", pgm, server); exit(4); } if (Verbose) printf("%s: joined %s as client id %d (%d clients)\n", pgm, server, id, nc); /* Register */ cuserid(me); event_register(AGENTDCLASS, AGENTDSPEC, me); /* Subscribe to only AGENTD type events */ event_select_type(0, ET_MIN, ET_MAX); event_select_type(1, ET_AGENTD_MIN, ET_AGENTD_MAX); /* Initialize agent control structures */ for (i = 0; i < MAX_AGENT; ++i) { Agent[i].pid = 0; Agent[i].status = AGENTD_AGENT_FREE; } mp_init(); /*(not strcitly necessary, since done in event land)*/ /* Allocate our locks and semaphores */ AgentLock = mp_alloclock(); Exitlock = mp_alloclock(); Exitwait = mp_allocsema(); ReadInit = mp_allocsema(); AgentInit = mp_allocsema(); /* * Loop forever processing agentd requests */ FOREVER { EVENT e; /* Wait for an event and then dispatch it */ event_wait(); if (!event_receive(&e)) continue; switch (e.ev_head.type) { case ET_AGENTD_REQ: agent_request((EVENT_AGENTD_REQ *)&e); break; default: if (Verbose) printf("Ignoring event \'%s\'(%d) from %d\n", event_lookup_name(e.ev_head.type), e.ev_head.type, e.ev_head.from); } } }
static void passkey_agent_reply(DBusPendingCall *call, void *user_data) { struct pending_agent_request *req = user_data; struct passkey_agent *agent = req->agent; pin_code_reply_cp pr; DBusMessage *message; DBusError err; size_t len; char *pin; /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { if (!req->old_if && !strcmp(err.name, DBUS_ERROR_UNKNOWN_METHOD)) { debug("New Request API failed, trying old one"); req->old_if = 1; dbus_error_free(&err); dbus_pending_call_unref(req->call); req->call = agent_request(req->path, &req->bda, agent, FALSE, 1); if (!req->call) goto fail; dbus_message_unref(message); dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL); return; } error("Passkey agent replied with an error: %s, %s", err.name, err.message); dbus_error_free(&err); goto fail; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID)) { error("Wrong passkey reply signature: %s", err.message); dbus_error_free(&err); goto fail; } len = strlen(pin); if (len > 16 || len < 1) { error("Invalid passkey length from handler"); goto fail; } set_pin_length(&req->sba, len); memset(&pr, 0, sizeof(pr)); bacpy(&pr.bdaddr, &req->bda); memcpy(pr.pin_code, pin, len); pr.pin_len = len; hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); goto done; fail: hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &req->bda); done: if (message) dbus_message_unref(message); agent->pending_requests = g_slist_remove(agent->pending_requests, req); dbus_pending_call_cancel(req->call); if (req->call) dbus_pending_call_unref(req->call); g_free(req->path); g_free(req); if (agent != default_agent) { agent->adapter->passkey_agents = g_slist_remove(agent->adapter->passkey_agents, agent); passkey_agent_free(agent); } }