|
63 | 63 | static char *userauth_list(LIBSSH2_SESSION *session, const char *username, |
64 | 64 | unsigned int username_len) |
65 | 65 | { |
66 | | - static const unsigned char reply_codes[3] = |
67 | | - { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 }; |
| 66 | + unsigned char reply_codes[4] = |
| 67 | + { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, |
| 68 | + SSH_MSG_USERAUTH_BANNER, 0 }; |
68 | 69 | /* packet_type(1) + username_len(4) + service_len(4) + |
69 | 70 | service(14)"ssh-connection" + method_len(4) = 27 */ |
70 | 71 | unsigned long methods_len; |
| 72 | + unsigned int banner_len; |
71 | 73 | unsigned char *s; |
72 | 74 | int rc; |
73 | 75 |
|
@@ -134,6 +136,57 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, |
134 | 136 | return NULL; |
135 | 137 | } |
136 | 138 |
|
| 139 | + if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_BANNER) { |
| 140 | + if(session->userauth_list_data_len < 5) { |
| 141 | + LIBSSH2_FREE(session, session->userauth_list_data); |
| 142 | + session->userauth_list_data = NULL; |
| 143 | + _libssh2_error(session, LIBSSH2_ERROR_PROTO, |
| 144 | + "Unexpected packet size"); |
| 145 | + return NULL; |
| 146 | + } |
| 147 | + banner_len = _libssh2_ntohu32(session->userauth_list_data + 1); |
| 148 | + if(banner_len >= session->userauth_list_data_len - 5) { |
| 149 | + LIBSSH2_FREE(session, session->userauth_list_data); |
| 150 | + session->userauth_list_data = NULL; |
| 151 | + _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, |
| 152 | + "Unexpected userauth banner size"); |
| 153 | + return NULL; |
| 154 | + } |
| 155 | + session->userauth_banner = LIBSSH2_ALLOC(session, banner_len); |
| 156 | + if(!session->userauth_banner) { |
| 157 | + LIBSSH2_FREE(session, session->userauth_list_data); |
| 158 | + session->userauth_list_data = NULL; |
| 159 | + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, |
| 160 | + "Unable to allocate memory for userauth_banner"); |
| 161 | + return NULL; |
| 162 | + } |
| 163 | + memmove(session->userauth_banner, session->userauth_list_data + 5, |
| 164 | + banner_len); |
| 165 | + session->userauth_banner[banner_len] = '\0'; |
| 166 | + _libssh2_debug(session, LIBSSH2_TRACE_AUTH, |
| 167 | + "Banner: %s", |
| 168 | + session->userauth_banner); |
| 169 | + LIBSSH2_FREE(session, session->userauth_list_data); |
| 170 | + session->userauth_list_data = NULL; |
| 171 | + /* SSH_MSG_USERAUTH_BANNER has been handled */ |
| 172 | + reply_codes[2] = 0; |
| 173 | + rc = _libssh2_packet_requirev(session, reply_codes, |
| 174 | + &session->userauth_list_data, |
| 175 | + &session->userauth_list_data_len, 0, |
| 176 | + NULL, 0, |
| 177 | + &session->userauth_list_packet_requirev_state); |
| 178 | + if(rc == LIBSSH2_ERROR_EAGAIN) { |
| 179 | + _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, |
| 180 | + "Would block requesting userauth list"); |
| 181 | + return NULL; |
| 182 | + } |
| 183 | + else if(rc || (session->userauth_list_data_len < 1)) { |
| 184 | + _libssh2_error(session, rc, "Failed getting response"); |
| 185 | + session->userauth_list_state = libssh2_NB_state_idle; |
| 186 | + return NULL; |
| 187 | + } |
| 188 | + } |
| 189 | + |
137 | 190 | if(session->userauth_list_data[0] == SSH_MSG_USERAUTH_SUCCESS) { |
138 | 191 | /* Wow, who'dve thought... */ |
139 | 192 | _libssh2_error(session, LIBSSH2_ERROR_NONE, "No error"); |
@@ -189,6 +242,30 @@ libssh2_userauth_list(LIBSSH2_SESSION * session, const char *user, |
189 | 242 | return ptr; |
190 | 243 | } |
191 | 244 |
|
| 245 | +/* libssh2_userauth_banner |
| 246 | + * |
| 247 | + * Retrieve banner message from server, if available. |
| 248 | + * When no such message is sent by server or if no authentication attempt has |
| 249 | + * been made, this function returns LIBSSH2_ERROR_MISSING_AUTH_BANNER. |
| 250 | + */ |
| 251 | +LIBSSH2_API int |
| 252 | +libssh2_userauth_banner(LIBSSH2_SESSION *session, char **banner) |
| 253 | +{ |
| 254 | + if(NULL == session) |
| 255 | + return LIBSSH2_ERROR_MISSING_USERAUTH_BANNER; |
| 256 | + |
| 257 | + if(!session->userauth_banner) { |
| 258 | + return _libssh2_error(session, |
| 259 | + LIBSSH2_ERROR_MISSING_USERAUTH_BANNER, |
| 260 | + "Missing userauth banner"); |
| 261 | + } |
| 262 | + |
| 263 | + if(banner != NULL) |
| 264 | + *banner = session->userauth_banner; |
| 265 | + |
| 266 | + return LIBSSH2_ERROR_NONE; |
| 267 | +} |
| 268 | + |
192 | 269 | /* |
193 | 270 | * libssh2_userauth_authenticated |
194 | 271 | * |
|
0 commit comments