diff options
Diffstat (limited to 'libs/libssh2/src/agent.c')
-rw-r--r-- | libs/libssh2/src/agent.c | 193 |
1 files changed, 121 insertions, 72 deletions
diff --git a/libs/libssh2/src/agent.c b/libs/libssh2/src/agent.c index c2ba422b65..0c8d881665 100644 --- a/libs/libssh2/src/agent.c +++ b/libs/libssh2/src/agent.c @@ -138,6 +138,8 @@ struct _LIBSSH2_AGENT struct agent_transaction_ctx transctx; struct agent_publickey *identity; struct list_head head; /* list of public keys */ + + char *identity_agent_path; /* Path to a custom identity agent socket */ }; #ifdef PF_UNIX @@ -147,22 +149,25 @@ agent_connect_unix(LIBSSH2_AGENT *agent) const char *path; struct sockaddr_un s_un; - path = getenv("SSH_AUTH_SOCK"); - if (!path) - return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, - "no auth sock variable"); + path = agent->identity_agent_path; + if(!path) { + path = getenv("SSH_AUTH_SOCK"); + if(!path) + return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, + "no auth sock variable"); + } agent->fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (agent->fd < 0) + if(agent->fd < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_SOCKET, "failed creating socket"); s_un.sun_family = AF_UNIX; - strncpy (s_un.sun_path, path, sizeof s_un.sun_path); - s_un.sun_path[sizeof(s_un.sun_path)-1]=0; /* make sure there's a trailing - zero */ - if (connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { - close (agent->fd); + strncpy(s_un.sun_path, path, sizeof s_un.sun_path); + s_un.sun_path[sizeof(s_un.sun_path)-1] = 0; /* make sure there's a trailing + zero */ + if(connect(agent->fd, (struct sockaddr*)(&s_un), sizeof s_un) != 0) { + close(agent->fd); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed connecting with agent"); } @@ -177,34 +182,34 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) int rc; /* Send the length of the request */ - if (transctx->state == agent_NB_state_request_created) { + if(transctx->state == agent_NB_state_request_created) { _libssh2_htonu32(buf, transctx->request_len); rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc == -EAGAIN) + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) + else if(rc < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent send failed"); transctx->state = agent_NB_state_request_length_sent; } /* Send the request body */ - if (transctx->state == agent_NB_state_request_length_sent) { + if(transctx->state == agent_NB_state_request_length_sent) { rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request, transctx->request_len, 0); - if (rc == -EAGAIN) + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; - else if (rc < 0) + else if(rc < 0) return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent send failed"); transctx->state = agent_NB_state_request_sent; } /* Receive the length of a response */ - if (transctx->state == agent_NB_state_request_sent) { + if(transctx->state == agent_NB_state_request_sent) { rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0); - if (rc < 0) { - if (rc == -EAGAIN) + if(rc < 0) { + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV, "agent recv failed"); @@ -212,18 +217,18 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) transctx->response_len = _libssh2_ntohu32(buf); transctx->response = LIBSSH2_ALLOC(agent->session, transctx->response_len); - if (!transctx->response) + if(!transctx->response) return LIBSSH2_ERROR_ALLOC; transctx->state = agent_NB_state_response_length_received; } /* Receive the response body */ - if (transctx->state == agent_NB_state_response_length_received) { + if(transctx->state == agent_NB_state_response_length_received) { rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response, transctx->response_len, 0); - if (rc < 0) { - if (rc == -EAGAIN) + if(rc < 0) { + if(rc == -EAGAIN) return LIBSSH2_ERROR_EAGAIN; return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND, "agent recv failed"); @@ -270,7 +275,7 @@ agent_connect_pageant(LIBSSH2_AGENT *agent) { HWND hwnd; hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) + if(!hwnd) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed connecting agent"); agent->fd = 0; /* Mark as the connection has been established */ @@ -288,25 +293,26 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) int id; COPYDATASTRUCT cds; - if (!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) + if(!transctx || 4 + transctx->request_len > PAGEANT_MAX_MSGLEN) return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL, "illegal input"); hwnd = FindWindow("Pageant", "Pageant"); - if (!hwnd) + if(!hwnd) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "found no pageant"); - sprintf(mapname, "PageantRequest%08x", (unsigned)GetCurrentThreadId()); + snprintf(mapname, sizeof(mapname), + "PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0'); filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, PAGEANT_MAX_MSGLEN, mapname); - if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) + if(filemap == NULL || filemap == INVALID_HANDLE_VALUE) return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed setting up pageant filemap"); p2 = p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); - if (p == NULL || p2 == NULL) { + if(p == NULL || p2 == NULL) { CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, "failed to open pageant filemap for writing"); @@ -320,9 +326,9 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) cds.lpData = mapname; id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); - if (id > 0) { + if(id > 0) { transctx->response_len = _libssh2_ntohu32(p); - if (transctx->response_len > PAGEANT_MAX_MSGLEN) { + if(transctx->response_len > PAGEANT_MAX_MSGLEN) { UnmapViewOfFile(p); CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL, @@ -330,7 +336,7 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx) } transctx->response = LIBSSH2_ALLOC(agent->session, transctx->response_len); - if (!transctx->response) { + if(!transctx->response) { UnmapViewOfFile(p); CloseHandle(filemap); return _libssh2_error(agent->session, LIBSSH2_ERROR_ALLOC, @@ -384,9 +390,9 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, int rc; /* Create a request to sign the data */ - if (transctx->state == agent_NB_state_init) { + if(transctx->state == agent_NB_state_init) { s = transctx->request = LIBSSH2_ALLOC(session, len); - if (!transctx->request) + if(!transctx->request) return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "out of memory"); @@ -405,17 +411,17 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, } /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_SIGN_REQUEST) + if(*transctx->request != SSH2_AGENTC_SIGN_REQUEST) return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "illegal request"); - if (!agent->ops) + if(!agent->ops) /* if no agent has been connected, bail out */ return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE, "agent not connected"); rc = agent->ops->transact(agent, transctx); - if (rc) { + if(rc) { goto error; } LIBSSH2_FREE(session, transctx->request); @@ -424,11 +430,11 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, len = transctx->response_len; s = transctx->response; len--; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } - if (*s != SSH2_AGENT_SIGN_RESPONSE) { + if(*s != SSH2_AGENT_SIGN_RESPONSE) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -436,7 +442,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Skip the entire length of the signature */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -444,14 +450,14 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Skip signing method */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } method_len = _libssh2_ntohu32(s); s += 4; len -= method_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -459,20 +465,20 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, /* Read the signature */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } *sig_len = _libssh2_ntohu32(s); s += 4; len -= *sig_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } *sig = LIBSSH2_ALLOC(session, *sig_len); - if (!*sig) { + if(!*sig) { rc = LIBSSH2_ERROR_ALLOC; goto error; } @@ -498,24 +504,24 @@ agent_list_identities(LIBSSH2_AGENT *agent) unsigned char c = SSH2_AGENTC_REQUEST_IDENTITIES; /* Create a request to list identities */ - if (transctx->state == agent_NB_state_init) { + if(transctx->state == agent_NB_state_init) { transctx->request = &c; transctx->request_len = 1; transctx->state = agent_NB_state_request_created; } /* Make sure to be re-called as a result of EAGAIN. */ - if (*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) + if(*transctx->request != SSH2_AGENTC_REQUEST_IDENTITIES) return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, "illegal agent request"); - if (!agent->ops) + if(!agent->ops) /* if no agent has been connected, bail out */ return _libssh2_error(agent->session, LIBSSH2_ERROR_BAD_USE, "agent not connected"); rc = agent->ops->transact(agent, transctx); - if (rc) { + if(rc) { goto error; } transctx->request = NULL; @@ -523,11 +529,11 @@ agent_list_identities(LIBSSH2_AGENT *agent) len = transctx->response_len; s = transctx->response; len--; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } - if (*s != SSH2_AGENT_IDENTITIES_ANSWER) { + if(*s != SSH2_AGENT_IDENTITIES_ANSWER) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } @@ -535,25 +541,25 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the length of identities */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } num_identities = _libssh2_ntohu32(s); s += 4; - while (num_identities--) { + while(num_identities--) { struct agent_publickey *identity; ssize_t comment_len; /* Read the length of the blob */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; goto error; } identity = LIBSSH2_ALLOC(agent->session, sizeof *identity); - if (!identity) { + if(!identity) { rc = LIBSSH2_ERROR_ALLOC; goto error; } @@ -562,7 +568,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the blob */ len -= identity->external.blob_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity); goto error; @@ -570,7 +576,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) identity->external.blob = LIBSSH2_ALLOC(agent->session, identity->external.blob_len); - if (!identity->external.blob) { + if(!identity->external.blob) { rc = LIBSSH2_ERROR_ALLOC; LIBSSH2_FREE(agent->session, identity); goto error; @@ -580,7 +586,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the length of the comment */ len -= 4; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -591,7 +597,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) /* Read the comment */ len -= comment_len; - if (len < 0) { + if(len < 0) { rc = LIBSSH2_ERROR_AGENT_PROTOCOL; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -600,7 +606,7 @@ agent_list_identities(LIBSSH2_AGENT *agent) identity->external.comment = LIBSSH2_ALLOC(agent->session, comment_len + 1); - if (!identity->external.comment) { + if(!identity->external.comment) { rc = LIBSSH2_ERROR_ALLOC; LIBSSH2_FREE(agent->session, identity->external.blob); LIBSSH2_FREE(agent->session, identity); @@ -621,11 +627,12 @@ agent_list_identities(LIBSSH2_AGENT *agent) } static void -agent_free_identities(LIBSSH2_AGENT *agent) { +agent_free_identities(LIBSSH2_AGENT *agent) +{ struct agent_publickey *node; struct agent_publickey *next; - for (node = _libssh2_list_first(&agent->head); node; node = next) { + for(node = _libssh2_list_first(&agent->head); node; node = next) { next = _libssh2_list_next(&node->node); LIBSSH2_FREE(agent->session, node->external.blob); LIBSSH2_FREE(agent->session, node->external.comment); @@ -664,13 +671,14 @@ libssh2_agent_init(LIBSSH2_SESSION *session) LIBSSH2_AGENT *agent; agent = LIBSSH2_CALLOC(session, sizeof *agent); - if (!agent) { + if(!agent) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate space for agent connection"); return NULL; } agent->fd = LIBSSH2_INVALID_SOCKET; agent->session = session; + agent->identity_agent_path = NULL; _libssh2_list_init(&agent->head); return agent; @@ -687,10 +695,10 @@ LIBSSH2_API int libssh2_agent_connect(LIBSSH2_AGENT *agent) { int i, rc = -1; - for (i = 0; supported_backends[i].name; i++) { + for(i = 0; supported_backends[i].name; i++) { agent->ops = supported_backends[i].ops; rc = (agent->ops->connect)(agent); - if (!rc) + if(!rc) return 0; } return rc; @@ -707,7 +715,7 @@ LIBSSH2_API int libssh2_agent_list_identities(LIBSSH2_AGENT *agent) { memset(&agent->transctx, 0, sizeof agent->transctx); - /* Abondon the last fetched identities */ + /* Abandon the last fetched identities */ agent_free_identities(agent); return agent_list_identities(agent); } @@ -730,7 +738,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent, struct libssh2_agent_publickey *oprev) { struct agent_publickey *node; - if (oprev && oprev->node) { + if(oprev && oprev->node) { /* we have a starting point */ struct agent_publickey *prev = oprev->node; @@ -740,7 +748,7 @@ libssh2_agent_get_identity(LIBSSH2_AGENT *agent, else node = _libssh2_list_first(&agent->head); - if (!node) + if(!node) /* no (more) node */ return 1; @@ -764,7 +772,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent, void *abstract = agent; int rc; - if (agent->session->userauth_pblc_state == libssh2_NB_state_idle) { + if(agent->session->userauth_pblc_state == libssh2_NB_state_idle) { memset(&agent->transctx, 0, sizeof agent->transctx); agent->identity = identity->node; } @@ -789,7 +797,7 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent, LIBSSH2_API int libssh2_agent_disconnect(LIBSSH2_AGENT *agent) { - if (agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) + if(agent->ops && agent->fd != LIBSSH2_INVALID_SOCKET) return agent->ops->disconnect(agent); return 0; } @@ -801,11 +809,52 @@ libssh2_agent_disconnect(LIBSSH2_AGENT *agent) * collection of public keys. */ LIBSSH2_API void -libssh2_agent_free(LIBSSH2_AGENT *agent) { +libssh2_agent_free(LIBSSH2_AGENT *agent) +{ /* Allow connection freeing when the socket has lost its connection */ - if (agent->fd != LIBSSH2_INVALID_SOCKET) { + if(agent->fd != LIBSSH2_INVALID_SOCKET) { libssh2_agent_disconnect(agent); } + + if(agent->identity_agent_path != NULL) + LIBSSH2_FREE(agent->session, agent->identity_agent_path); + agent_free_identities(agent); LIBSSH2_FREE(agent->session, agent); } + +/* + * libssh2_agent_set_identity_path() + * + * Allows a custom agent socket path beyond SSH_AUTH_SOCK env + * + */ +LIBSSH2_API void +libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, const char *path) +{ + if(agent->identity_agent_path) { + LIBSSH2_FREE(agent->session, agent->identity_agent_path); + agent->identity_agent_path = NULL; + } + + if(path) { + size_t path_len = strlen(path); + if(path_len < SIZE_MAX - 1) { + char *path_buf = LIBSSH2_ALLOC(agent->session, path_len + 1); + memcpy(path_buf, path, path_len); + path_buf[path_len] = '\0'; + agent->identity_agent_path = path_buf; + } + } +} + +/* + * libssh2_agent_get_identity_path() + * + * Returns the custom agent socket path if set + * + */ +LIBSSH2_API const char *libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent) +{ + return agent->identity_agent_path; +} |