|
Packit Service |
31306d |
/**
|
|
Packit Service |
31306d |
@page libssh_tutor_authentication Chapter 2: A deeper insight on authentication
|
|
Packit Service |
31306d |
@section authentication_details A deeper insight on authentication
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
In our guided tour, we merely mentioned that the user needed to authenticate.
|
|
Packit Service |
31306d |
We didn't explain much in detail how that was supposed to happen.
|
|
Packit Service |
31306d |
This chapter explains better the four authentication methods: with public keys,
|
|
Packit Service |
31306d |
with a password, with challenges and responses (keyboard-interactive), and with
|
|
Packit Service |
31306d |
no authentication at all.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
If your software is supposed to connect to an arbitrary server, then you
|
|
Packit Service |
31306d |
might need to support all authentication methods. If your software will
|
|
Packit Service |
31306d |
connect only to a given server, then it might be enough for your software
|
|
Packit Service |
31306d |
to support only the authentication methods used by that server. If you are
|
|
Packit Service |
31306d |
the administrator of the server, it might be your call to choose those
|
|
Packit Service |
31306d |
authentication methods.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
It is not the purpose of this document to review in detail the advantages
|
|
Packit Service |
31306d |
and drawbacks of each authentication method. You are therefore invited
|
|
Packit Service |
31306d |
to read the abundant documentation on this topic to fully understand the
|
|
Packit Service |
31306d |
advantages and security risks linked to each method.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection pubkeys Authenticating with public keys
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
libssh is fully compatible with the openssh public and private keys. You
|
|
Packit Service |
31306d |
can either use the automatic public key authentication method provided by
|
|
Packit Service |
31306d |
libssh, or roll your own using the public key functions.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The process of authenticating by public key to a server is the following:
|
|
Packit Service |
31306d |
- you scan a list of files that contain public keys. each key is sent to
|
|
Packit Service |
31306d |
the SSH server, until the server acknowledges a key (a key it knows can be
|
|
Packit Service |
31306d |
used to authenticate the user).
|
|
Packit Service |
31306d |
- then, you retrieve the private key for this key and send a message
|
|
Packit Service |
31306d |
proving that you know that private key.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The function ssh_userauth_autopubkey() does this using the available keys in
|
|
Packit Service |
31306d |
"~/.ssh/". The return values are the following:
|
|
Packit Service |
31306d |
- SSH_AUTH_ERROR: some serious error happened during authentication
|
|
Packit Service |
31306d |
- SSH_AUTH_DENIED: no key matched
|
|
Packit Service |
31306d |
- SSH_AUTH_SUCCESS: you are now authenticated
|
|
Packit Service |
31306d |
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
|
|
Packit Service |
31306d |
mean of authentication (like a password).
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The ssh_userauth_publickey_auto() function also tries to authenticate using the
|
|
Packit Service |
31306d |
SSH agent, if you have one running, or the "none" method otherwise.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
If you wish to authenticate with public key by your own, follow these steps:
|
|
Packit Service |
31306d |
- Retrieve the public key with ssh_pki_import_pubkey_file().
|
|
Packit Service |
31306d |
- Offer the public key to the SSH server using ssh_userauth_try_publickey().
|
|
Packit Service |
31306d |
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
|
Packit Service |
31306d |
authenticate using the public key and you can go to the next step.
|
|
Packit Service |
31306d |
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
|
|
Packit Service |
31306d |
If a passphrase is needed, either the passphrase specified as argument or
|
|
Packit Service |
31306d |
a callback will be used.
|
|
Packit Service |
31306d |
- Authenticate using ssh_userauth_publickey() with your private key.
|
|
Packit Service |
31306d |
- Do not forget cleaning up memory using ssh_key_free().
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Here is a minimalistic example of public key authentication:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int authenticate_pubkey(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_ERROR)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
fprintf(stderr, "Authentication failed: %s\n",
|
|
Packit Service |
31306d |
ssh_get_error(session));
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@see ssh_userauth_publickey_auto()
|
|
Packit Service |
31306d |
@see ssh_userauth_try_publickey()
|
|
Packit Service |
31306d |
@see ssh_userauth_publickey()
|
|
Packit Service |
31306d |
@see ssh_pki_import_pubkey_file()
|
|
Packit Service |
31306d |
@see ssh_pki_import_privkey_file()
|
|
Packit Service |
31306d |
@see ssh_key_free()
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection password Authenticating with a password
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The function ssh_userauth_password() serves the purpose of authenticating
|
|
Packit Service |
31306d |
using a password. It will return SSH_AUTH_SUCCESS if the password worked,
|
|
Packit Service |
31306d |
or one of other constants otherwise. It's your work to ask the password
|
|
Packit Service |
31306d |
and to deallocate it in a secure manner.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
If your server complains that the password is wrong, but you can still
|
|
Packit Service |
31306d |
authenticate using openssh's client (issuing password), it's probably
|
|
Packit Service |
31306d |
because openssh only accept keyboard-interactive. Switch to
|
|
Packit Service |
31306d |
keyboard-interactive authentication, or try to configure plain text passwords
|
|
Packit Service |
31306d |
on the SSH server.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Here is a small example of password authentication:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int authenticate_password(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char *password;
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
password = getpass("Enter your password: ");
|
|
Packit Service |
31306d |
rc = ssh_userauth_password(session, NULL, password);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_ERROR)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
fprintf(stderr, "Authentication failed: %s\n",
|
|
Packit Service |
31306d |
ssh_get_error(session));
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@see ssh_userauth_password
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection keyb_int The keyboard-interactive authentication method
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The keyboard-interactive method is, as its name tells, interactive. The
|
|
Packit Service |
31306d |
server will issue one or more challenges that the user has to answer,
|
|
Packit Service |
31306d |
until the server takes an authentication decision.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
|
Packit Service |
31306d |
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
|
Packit Service |
31306d |
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The keyboard-interactive authentication method of SSH2 is a feature that
|
|
Packit Service |
31306d |
permits the server to ask a certain number of questions in an interactive
|
|
Packit Service |
31306d |
manner to the client, until it decides to accept or deny the login.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
To begin, you call ssh_userauth_kbdint() (just set user and submethods to
|
|
Packit Service |
31306d |
NULL) and store the answer.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
If the answer is SSH_AUTH_INFO, it means that the server has sent a few
|
|
Packit Service |
31306d |
questions that you should ask the user. You can retrieve these questions
|
|
Packit Service |
31306d |
with the following functions: ssh_userauth_kbdint_getnprompts(),
|
|
Packit Service |
31306d |
ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
|
|
Packit Service |
31306d |
ssh_userauth_kbdint_getprompt().
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Set the answer for each question in the challenge using
|
|
Packit Service |
31306d |
ssh_userauth_kbdint_setanswer().
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Then, call again ssh_userauth_kbdint() and start the process again until
|
|
Packit Service |
31306d |
these functions returns something else than SSH_AUTH_INFO.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Here are a few remarks:
|
|
Packit Service |
31306d |
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
|
Packit Service |
31306d |
- The server can send an empty question set (this is the default behavior
|
|
Packit Service |
31306d |
on my system) after you have sent the answers to the first questions.
|
|
Packit Service |
31306d |
You must still parse the answer, it might contain some
|
|
Packit Service |
31306d |
message from the server saying hello or such things. Just call
|
|
Packit Service |
31306d |
ssh_userauth_kbdint() until needed.
|
|
Packit Service |
31306d |
- The meaning of "name", "prompt", "instruction" may be a little
|
|
Packit Service |
31306d |
confusing. An explanation is given in the RFC section that follows.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
Here is a little note about how to use the information from
|
|
Packit Service |
31306d |
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@verbatim
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
3.3 User Interface Upon receiving a request message, the client SHOULD
|
|
Packit Service |
31306d |
prompt the user as follows: A command line interface (CLI) client SHOULD
|
|
Packit Service |
31306d |
print the name and instruction (if non-empty), adding newlines. Then for
|
|
Packit Service |
31306d |
each prompt in turn, the client SHOULD display the prompt and read the
|
|
Packit Service |
31306d |
user input.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
A graphical user interface (GUI) client has many choices on how to prompt
|
|
Packit Service |
31306d |
the user. One possibility is to use the name field (possibly prefixed
|
|
Packit Service |
31306d |
with the application's name) as the title of a dialog window in which
|
|
Packit Service |
31306d |
the prompt(s) are presented. In that dialog window, the instruction field
|
|
Packit Service |
31306d |
would be a text message, and the prompts would be labels for text entry
|
|
Packit Service |
31306d |
fields. All fields SHOULD be presented to the user, for example an
|
|
Packit Service |
31306d |
implementation SHOULD NOT discard the name field because its windows lack
|
|
Packit Service |
31306d |
titles; it SHOULD instead find another way to display this information. If
|
|
Packit Service |
31306d |
prompts are presented in a dialog window, then the client SHOULD NOT
|
|
Packit Service |
31306d |
present each prompt in a separate window.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
All clients MUST properly handle an instruction field with embedded
|
|
Packit Service |
31306d |
newlines. They SHOULD also be able to display at least 30 characters for
|
|
Packit Service |
31306d |
the name and prompts. If the server presents names or prompts longer than 30
|
|
Packit Service |
31306d |
characters, the client MAY truncate these fields to the length it can
|
|
Packit Service |
31306d |
display. If the client does truncate any fields, there MUST be an obvious
|
|
Packit Service |
31306d |
indication that such truncation has occurred.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
|
Packit Service |
31306d |
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
|
Packit Service |
31306d |
including terminal control characters in the fields to be displayed.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
For each prompt, the corresponding echo field indicates whether or not
|
|
Packit Service |
31306d |
the user input should be echoed as characters are typed. Clients SHOULD
|
|
Packit Service |
31306d |
correctly echo/mask user input for each prompt independently of other
|
|
Packit Service |
31306d |
prompts in the request message. If a client does not honor the echo field
|
|
Packit Service |
31306d |
for whatever reason, then the client MUST err on the side of
|
|
Packit Service |
31306d |
masking input. A GUI client might like to have a checkbox toggling
|
|
Packit Service |
31306d |
echo/mask. Clients SHOULD NOT add any additional characters to the prompt
|
|
Packit Service |
31306d |
such as ": " (colon-space); the server is responsible for supplying all
|
|
Packit Service |
31306d |
text to be displayed to the user. Clients MUST also accept empty responses
|
|
Packit Service |
31306d |
from the user and pass them on as empty strings.
|
|
Packit Service |
31306d |
@endverbatim
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The following example shows how to perform keyboard-interactive authentication:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int authenticate_kbdint(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
|
Packit Service |
31306d |
while (rc == SSH_AUTH_INFO)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
const char *name, *instruction;
|
|
Packit Service |
31306d |
int nprompts, iprompt;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
name = ssh_userauth_kbdint_getname(session);
|
|
Packit Service |
31306d |
instruction = ssh_userauth_kbdint_getinstruction(session);
|
|
Packit Service |
31306d |
nprompts = ssh_userauth_kbdint_getnprompts(session);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (strlen(name) > 0)
|
|
Packit Service |
31306d |
printf("%s\n", name);
|
|
Packit Service |
31306d |
if (strlen(instruction) > 0)
|
|
Packit Service |
31306d |
printf("%s\n", instruction);
|
|
Packit Service |
31306d |
for (iprompt = 0; iprompt < nprompts; iprompt++)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
const char *prompt;
|
|
Packit Service |
31306d |
char echo;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
|
|
Packit Service |
31306d |
if (echo)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char buffer[128], *ptr;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
printf("%s", prompt);
|
|
Packit Service |
31306d |
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
buffer[sizeof(buffer) - 1] = '\0';
|
|
Packit Service |
31306d |
if ((ptr = strchr(buffer, '\n')) != NULL)
|
|
Packit Service |
31306d |
*ptr = '\0';
|
|
Packit Service |
31306d |
if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
memset(buffer, 0, strlen(buffer));
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
else
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
char *ptr;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
ptr = getpass(prompt);
|
|
Packit Service |
31306d |
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint()
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint_getnprompts()
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint_getname()
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint_getinstruction()
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint_getprompt()
|
|
Packit Service |
31306d |
@see ssh_userauth_kbdint_setanswer()
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection none Authenticating with "none" method
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The primary purpose of the "none" method is to get authenticated **without**
|
|
Packit Service |
31306d |
any credential. Don't do that, use one of the other authentication methods,
|
|
Packit Service |
31306d |
unless you really want to grant anonymous access.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
If the account has no password, and if the server is configured to let you
|
|
Packit Service |
31306d |
pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The following example shows how to perform "none" authentication:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int authenticate_none(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_userauth_none(session, NULL);
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection auth_list Getting the list of supported authentications
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
You are not meant to choose a given authentication method, you can
|
|
Packit Service |
31306d |
let the server tell you which methods are available. Once you know them,
|
|
Packit Service |
31306d |
you try them one after the other.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The following example shows how to get the list of available authentication
|
|
Packit Service |
31306d |
methods with ssh_userauth_list() and how to use the result:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int test_several_auth_methods(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int method, rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
rc = ssh_userauth_none(session, NULL);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_ERROR) {
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
method = ssh_userauth_list(session, NULL);
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
if (method & SSH_AUTH_METHOD_NONE)
|
|
Packit Service |
31306d |
{ // For the source code of function authenticate_none(),
|
|
Packit Service |
31306d |
// refer to the corresponding example
|
|
Packit Service |
31306d |
rc = authenticate_none(session);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_SUCCESS) return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (method & SSH_AUTH_METHOD_PUBLICKEY)
|
|
Packit Service |
31306d |
{ // For the source code of function authenticate_pubkey(),
|
|
Packit Service |
31306d |
// refer to the corresponding example
|
|
Packit Service |
31306d |
rc = authenticate_pubkey(session);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_SUCCESS) return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (method & SSH_AUTH_METHOD_INTERACTIVE)
|
|
Packit Service |
31306d |
{ // For the source code of function authenticate_kbdint(),
|
|
Packit Service |
31306d |
// refer to the corresponding example
|
|
Packit Service |
31306d |
rc = authenticate_kbdint(session);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_SUCCESS) return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
if (method & SSH_AUTH_METHOD_PASSWORD)
|
|
Packit Service |
31306d |
{ // For the source code of function authenticate_password(),
|
|
Packit Service |
31306d |
// refer to the corresponding example
|
|
Packit Service |
31306d |
rc = authenticate_password(session);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_SUCCESS) return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
return SSH_AUTH_ERROR;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@subsection banner Getting the banner
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The SSH server might send a banner, which you can retrieve with
|
|
Packit Service |
31306d |
ssh_get_issue_banner(), then display to the user.
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
The following example shows how to retrieve and dispose the issue banner:
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
@code
|
|
Packit Service |
31306d |
int display_banner(ssh_session session)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
int rc;
|
|
Packit Service |
31306d |
char *banner;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
/*
|
|
Packit Service |
31306d |
*** Does not work without calling ssh_userauth_none() first ***
|
|
Packit Service |
31306d |
*** That will be fixed ***
|
|
Packit Service |
31306d |
*/
|
|
Packit Service |
31306d |
rc = ssh_userauth_none(session, NULL);
|
|
Packit Service |
31306d |
if (rc == SSH_AUTH_ERROR)
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
banner = ssh_get_issue_banner(session);
|
|
Packit Service |
31306d |
if (banner)
|
|
Packit Service |
31306d |
{
|
|
Packit Service |
31306d |
printf("%s\n", banner);
|
|
Packit Service |
31306d |
free(banner);
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
return rc;
|
|
Packit Service |
31306d |
}
|
|
Packit Service |
31306d |
@endcode
|
|
Packit Service |
31306d |
|
|
Packit Service |
31306d |
*/
|