/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> * Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net> * Copyright (c) 2009-2011 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "libssh2_priv.h" #include <ctype.h>#include <stdio.h> #include <assert.h> /* Needed for struct iovec on some platforms */#ifdef HAVE_SYS_UIO_H#include <sys/uio.h>#endif #include "transport.h"#include "session.h"#include "userauth.h" /* libssh2_userauth_list * * List authentication methods * Will yield successful login if "none" happens to be allowable for this user * Not a common configuration for any SSH server though * username should be NULL, or a null terminated string */static char *userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len){ static const unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + method_len(4) = 27 */ unsigned long methods_len; unsigned char *s; int rc; if (session->userauth_list_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_list_packet_requirev_state, 0, sizeof(session->userauth_list_packet_requirev_state)); session->userauth_list_data_len = username_len + 27; s = session->userauth_list_data = LIBSSH2_ALLOC(session, session->userauth_list_data_len); if (!session->userauth_list_data) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth_list"); return NULL; } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", 14); _libssh2_store_u32(&s, 4); /* send "none" separately */ session->userauth_list_state = libssh2_NB_state_created; } if (session->userauth_list_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_list_data, session->userauth_list_data_len, (unsigned char *)"none", 4); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; } /* now free the packet that was sent */ LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; if (rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-none request"); session->userauth_list_state = libssh2_NB_state_idle; return NULL; } session->userauth_list_state = libssh2_NB_state_sent; } if (session->userauth_list_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_list_data, &session->userauth_list_data_len, 0, NULL, 0, &session->userauth_list_packet_requirev_state); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; } else if (rc) { _libssh2_error(session, rc, "Failed getting response"); session->userauth_list_state = libssh2_NB_state_idle; return NULL; } if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { /* Wow, who'dve thought... */ _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error"); LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; session->state |= LIBSSH2_STATE_AUTHENTICATED; session->userauth_list_state = libssh2_NB_state_idle; return NULL; } methods_len = _libssh2_ntohu32(session->userauth_list_data + 1); /* Do note that the memory areas overlap! */ memmove(session->userauth_list_data, session->userauth_list_data + 5, methods_len); session->userauth_list_data[methods_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Permitted auth methods: %s", session->userauth_list_data); } session->userauth_list_state = libssh2_NB_state_idle; return (char *) session->userauth_list_data;} /* libssh2_userauth_list * * List authentication methods * Will yield successful login if "none" happens to be allowable for this user * Not a common configuration for any SSH server though * username should be NULL, or a null terminated string */LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user, unsigned int user_len){ char *ptr; BLOCK_ADJUST_ERRNO(ptr, session, userauth_list(session, user, user_len)); return ptr;} /* * libssh2_userauth_authenticated * * Returns: 0 if not yet authenticated * 1 if already authenticated */LIBSSH2_API intlibssh2_userauth_authenticated(LIBSSH2_SESSION * session){ return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0;} /* userauth_password * Plain ol' login */static intuserauth_password(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const unsigned char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))){ unsigned char *s; static const unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0 }; int rc; if (session->userauth_pswd_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_pswd_packet_requirev_state, 0, sizeof(session->userauth_pswd_packet_requirev_state)); /* * 40 = acket_type(1) + username_len(4) + service_len(4) + * service(14)"ssh-connection" + method_len(4) + method(8)"password" + * chgpwdbool(1) + password_len(4) */ session->userauth_pswd_data_len = username_len + 40; session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; /* TODO: remove this alloc with a fixed buffer in the session struct */ s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); if (!session->userauth_pswd_data) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "userauth-password request"); } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = '\0'; _libssh2_store_u32(&s, password_len); /* 'password' is sent separately */ _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Attempting to login using password authentication"); session->userauth_pswd_state = libssh2_NB_state_created; } if (session->userauth_pswd_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_pswd_data, session->userauth_pswd_data_len, password, password_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block writing password request"); } /* now free the sent packet */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; if (rc) { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password request"); } session->userauth_pswd_state = libssh2_NB_state_sent; } password_response: if ((session->userauth_pswd_state == libssh2_NB_state_sent) || (session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { if (session->userauth_pswd_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_pswd_data, &session->userauth_pswd_data_len, 0, NULL, 0, &session-> userauth_pswd_packet_requirev_state); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting"); } else if (rc) { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Would block waiting"); } if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication successful"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->state |= LIBSSH2_STATE_AUTHENTICATED; session->userauth_pswd_state = libssh2_NB_state_idle; return 0; } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication failed"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, "Authentication failed " "(username/password)"); } session->userauth_pswd_newpw = NULL; session->userauth_pswd_newpw_len = 0; session->userauth_pswd_state = libssh2_NB_state_sent1; } if ((session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) || (session->userauth_pswd_data0 == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) { session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; if ((session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { if (session->userauth_pswd_state == libssh2_NB_state_sent1) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password change required"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; } if (passwd_change_cb) { if (session->userauth_pswd_state == libssh2_NB_state_sent1) { passwd_change_cb(session, &session->userauth_pswd_newpw, &session->userauth_pswd_newpw_len, &session->abstract); if (!session->userauth_pswd_newpw) { return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and " "callback failed"); } /* basic data_len + newpw_len(4) */ session->userauth_pswd_data_len = username_len + password_len + 44; s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); if (!session->userauth_pswd_data) { LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory " "for userauth password " "change request"); } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = 0x01; _libssh2_store_str(&s, (char *)password, password_len); _libssh2_store_u32(&s, session->userauth_pswd_newpw_len); /* send session->userauth_pswd_newpw separately */ session->userauth_pswd_state = libssh2_NB_state_sent2; } if (session->userauth_pswd_state == libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, session->userauth_pswd_data, session->userauth_pswd_data_len, (unsigned char *) session->userauth_pswd_newpw, session->userauth_pswd_newpw_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting"); } /* free the allocated packets again */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; if (rc) { return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth " "password-change request"); } /* * Ugliest use of goto ever. Blame it on the * askN => requirev migration. */ session->userauth_pswd_state = libssh2_NB_state_sent; goto password_response; } } } else { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback " "specified"); } } } /* FAILURE */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, "Authentication failed");} /* * libssh2_userauth_password_ex * * Plain ol' login */ LIBSSH2_API intlibssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))){ int rc; BLOCK_ADJUST(rc, session, userauth_password(session, username, username_len, (unsigned char *)password, password_len, passwd_change_cb)); return rc;} /* * file_read_publickey * * Read a public key from an id_???.pub style file * * Returns an allocated string containing the decoded key in *pubkeydata * on success. * Returns an allocated string containing the key method (e.g. "ssh-dss") * in method on success. */static intfile_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, size_t *method_len, unsigned char **pubkeydata, size_t *pubkeydata_len, const char *pubkeyfile){ FILE *fd; char c; unsigned char *pubkey = NULL, *sp1, *sp2, *tmp; size_t pubkey_len = 0; unsigned int tmp_len; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s", pubkeyfile); /* Read Public Key */ fd = fopen(pubkeyfile, "r"); if (!fd) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to open public key file"); } while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') pubkey_len++; if (feof(fd)) { /* the last character was EOF */ pubkey_len--; } rewind(fd); if (pubkey_len <= 1) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid data in public key file"); } pubkey = LIBSSH2_ALLOC(session, pubkey_len); if (!pubkey) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for public key data"); } if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { LIBSSH2_FREE(session, pubkey); fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to read public key from file"); }Lines 1–500 of 1687. Load more
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> * Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net> * Copyright (c) 2009-2011 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "libssh2_priv.h" #include <ctype.h> #include <stdio.h> #include <assert.h> /* Needed for struct iovec on some platforms */ #ifdef HAVE_SYS_UIO_H #include <sys/uio.h> #endif #include "transport.h" #include "session.h" #include "userauth.h" /* libssh2_userauth_list * * List authentication methods * Will yield successful login if "none" happens to be allowable for this user * Not a common configuration for any SSH server though * username should be NULL, or a null terminated string */ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len) { static const unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + method_len(4) = 27 */ unsigned long methods_len; unsigned char *s; int rc; if (session->userauth_list_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_list_packet_requirev_state, 0, sizeof(session->userauth_list_packet_requirev_state)); session->userauth_list_data_len = username_len + 27; s = session->userauth_list_data = LIBSSH2_ALLOC(session, session->userauth_list_data_len); if (!session->userauth_list_data) { _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth_list"); return NULL; } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", 14); _libssh2_store_u32(&s, 4); /* send "none" separately */ session->userauth_list_state = libssh2_NB_state_created; } if (session->userauth_list_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_list_data, session->userauth_list_data_len, (unsigned char *)"none", 4); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; } /* now free the packet that was sent */ LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; if (rc) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-none request"); session->userauth_list_state = libssh2_NB_state_idle; return NULL; } session->userauth_list_state = libssh2_NB_state_sent; } if (session->userauth_list_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_list_data, &session->userauth_list_data_len, 0, NULL, 0, &session->userauth_list_packet_requirev_state); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); return NULL; } else if (rc) { _libssh2_error(session, rc, "Failed getting response"); session->userauth_list_state = libssh2_NB_state_idle; return NULL; } if (session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { /* Wow, who'dve thought... */ _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error"); LIBSSH2_FREE(session, session->userauth_list_data); session->userauth_list_data = NULL; session->state |= LIBSSH2_STATE_AUTHENTICATED; session->userauth_list_state = libssh2_NB_state_idle; return NULL; } methods_len = _libssh2_ntohu32(session->userauth_list_data + 1); /* Do note that the memory areas overlap! */ memmove(session->userauth_list_data, session->userauth_list_data + 5, methods_len); session->userauth_list_data[methods_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Permitted auth methods: %s", session->userauth_list_data); } session->userauth_list_state = libssh2_NB_state_idle; return (char *) session->userauth_list_data; } /* libssh2_userauth_list * * List authentication methods * Will yield successful login if "none" happens to be allowable for this user * Not a common configuration for any SSH server though * username should be NULL, or a null terminated string */ LIBSSH2_API char * libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user, unsigned int user_len) { char *ptr; BLOCK_ADJUST_ERRNO(ptr, session, userauth_list(session, user, user_len)); return ptr; } /* * libssh2_userauth_authenticated * * Returns: 0 if not yet authenticated * 1 if already authenticated */ LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION * session) { return (session->state & LIBSSH2_STATE_AUTHENTICATED)?1:0; } /* userauth_password * Plain ol' login */ static int userauth_password(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const unsigned char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) { unsigned char *s; static const unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0 }; int rc; if (session->userauth_pswd_state == libssh2_NB_state_idle) { /* Zero the whole thing out */ memset(&session->userauth_pswd_packet_requirev_state, 0, sizeof(session->userauth_pswd_packet_requirev_state)); /* * 40 = acket_type(1) + username_len(4) + service_len(4) + * service(14)"ssh-connection" + method_len(4) + method(8)"password" + * chgpwdbool(1) + password_len(4) */ session->userauth_pswd_data_len = username_len + 40; session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; /* TODO: remove this alloc with a fixed buffer in the session struct */ s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); if (!session->userauth_pswd_data) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for " "userauth-password request"); } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = '\0'; _libssh2_store_u32(&s, password_len); /* 'password' is sent separately */ _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Attempting to login using password authentication"); session->userauth_pswd_state = libssh2_NB_state_created; } if (session->userauth_pswd_state == libssh2_NB_state_created) { rc = _libssh2_transport_send(session, session->userauth_pswd_data, session->userauth_pswd_data_len, password, password_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block writing password request"); } /* now free the sent packet */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; if (rc) { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password request"); } session->userauth_pswd_state = libssh2_NB_state_sent; } password_response: if ((session->userauth_pswd_state == libssh2_NB_state_sent) || (session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { if (session->userauth_pswd_state == libssh2_NB_state_sent) { rc = _libssh2_packet_requirev(session, reply_codes, &session->userauth_pswd_data, &session->userauth_pswd_data_len, 0, NULL, 0, &session-> userauth_pswd_packet_requirev_state); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting"); } else if (rc) { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT, "Would block waiting"); } if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication successful"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->state |= LIBSSH2_STATE_AUTHENTICATED; session->userauth_pswd_state = libssh2_NB_state_idle; return 0; } else if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_FAILURE) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password authentication failed"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, "Authentication failed " "(username/password)"); } session->userauth_pswd_newpw = NULL; session->userauth_pswd_newpw_len = 0; session->userauth_pswd_state = libssh2_NB_state_sent1; } if ((session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) || (session->userauth_pswd_data0 == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)) { session->userauth_pswd_data0 = SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; if ((session->userauth_pswd_state == libssh2_NB_state_sent1) || (session->userauth_pswd_state == libssh2_NB_state_sent2)) { if (session->userauth_pswd_state == libssh2_NB_state_sent1) { _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Password change required"); LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; } if (passwd_change_cb) { if (session->userauth_pswd_state == libssh2_NB_state_sent1) { passwd_change_cb(session, &session->userauth_pswd_newpw, &session->userauth_pswd_newpw_len, &session->abstract); if (!session->userauth_pswd_newpw) { return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and " "callback failed"); } /* basic data_len + newpw_len(4) */ session->userauth_pswd_data_len = username_len + password_len + 44; s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); if (!session->userauth_pswd_data) { LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory " "for userauth password " "change request"); } *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = 0x01; _libssh2_store_str(&s, (char *)password, password_len); _libssh2_store_u32(&s, session->userauth_pswd_newpw_len); /* send session->userauth_pswd_newpw separately */ session->userauth_pswd_state = libssh2_NB_state_sent2; } if (session->userauth_pswd_state == libssh2_NB_state_sent2) { rc = _libssh2_transport_send(session, session->userauth_pswd_data, session->userauth_pswd_data_len, (unsigned char *) session->userauth_pswd_newpw, session->userauth_pswd_newpw_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting"); } /* free the allocated packets again */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; LIBSSH2_FREE(session, session->userauth_pswd_newpw); session->userauth_pswd_newpw = NULL; if (rc) { return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth " "password-change request"); } /* * Ugliest use of goto ever. Blame it on the * askN => requirev migration. */ session->userauth_pswd_state = libssh2_NB_state_sent; goto password_response; } } } else { session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback " "specified"); } } } /* FAILURE */ LIBSSH2_FREE(session, session->userauth_pswd_data); session->userauth_pswd_data = NULL; session->userauth_pswd_state = libssh2_NB_state_idle; return _libssh2_error(session, LIBSSH2_ERROR_AUTHENTICATION_FAILED, "Authentication failed"); } /* * libssh2_userauth_password_ex * * Plain ol' login */ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, unsigned int username_len, const char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) { int rc; BLOCK_ADJUST(rc, session, userauth_password(session, username, username_len, (unsigned char *)password, password_len, passwd_change_cb)); return rc; } /* * file_read_publickey * * Read a public key from an id_???.pub style file * * Returns an allocated string containing the decoded key in *pubkeydata * on success. * Returns an allocated string containing the key method (e.g. "ssh-dss") * in method on success. */ static int file_read_publickey(LIBSSH2_SESSION * session, unsigned char **method, size_t *method_len, unsigned char **pubkeydata, size_t *pubkeydata_len, const char *pubkeyfile) { FILE *fd; char c; unsigned char *pubkey = NULL, *sp1, *sp2, *tmp; size_t pubkey_len = 0; unsigned int tmp_len; _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Loading public key file: %s", pubkeyfile); /* Read Public Key */ fd = fopen(pubkeyfile, "r"); if (!fd) { return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to open public key file"); } while (!feof(fd) && 1 == fread(&c, 1, 1, fd) && c != '\r' && c != '\n') pubkey_len++; if (feof(fd)) { /* the last character was EOF */ pubkey_len--; } rewind(fd); if (pubkey_len <= 1) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Invalid data in public key file"); } pubkey = LIBSSH2_ALLOC(session, pubkey_len); if (!pubkey) { fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for public key data"); } if (fread(pubkey, 1, pubkey_len, fd) != pubkey_len) { LIBSSH2_FREE(session, pubkey); fclose(fd); return _libssh2_error(session, LIBSSH2_ERROR_FILE, "Unable to read public key from file"); }