audit.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  14. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  15. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  16. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "includes.h"
  25. #include <stdarg.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. #ifdef SSH_AUDIT_EVENTS
  29. #include "audit.h"
  30. #include "log.h"
  31. #include "hostfile.h"
  32. #include "auth.h"
  33. #include "ssh-gss.h"
  34. #include "monitor_wrap.h"
  35. #include "xmalloc.h"
  36. #include "misc.h"
  37. #include "servconf.h"
  38. #include "ssherr.h"
  39. /*
  40. * Care must be taken when using this since it WILL NOT be initialized when
  41. * audit_connection_from() is called and MAY NOT be initialized when
  42. * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
  43. */
  44. extern Authctxt *the_authctxt;
  45. extern ServerOptions options;
  46. /* Maybe add the audit class to struct Authmethod? */
  47. ssh_audit_event_t
  48. audit_classify_auth(const char *method)
  49. {
  50. if (strcmp(method, "none") == 0)
  51. return SSH_AUTH_FAIL_NONE;
  52. else if (strcmp(method, "password") == 0)
  53. return SSH_AUTH_FAIL_PASSWD;
  54. else if (strcmp(method, "publickey") == 0 ||
  55. strcmp(method, "rsa") == 0)
  56. return SSH_AUTH_FAIL_PUBKEY;
  57. else if (strncmp(method, "keyboard-interactive", 20) == 0 ||
  58. strcmp(method, "challenge-response") == 0)
  59. return SSH_AUTH_FAIL_KBDINT;
  60. else if (strcmp(method, "hostbased") == 0 ||
  61. strcmp(method, "rhosts-rsa") == 0)
  62. return SSH_AUTH_FAIL_HOSTBASED;
  63. else if (strcmp(method, "gssapi-with-mic") == 0)
  64. return SSH_AUTH_FAIL_GSSAPI;
  65. else
  66. return SSH_AUDIT_UNKNOWN;
  67. }
  68. /* helper to return supplied username */
  69. const char *
  70. audit_username(void)
  71. {
  72. static const char unknownuser[] = "(unknown)";
  73. if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid)
  74. return (unknownuser);
  75. return (the_authctxt->user);
  76. }
  77. const char *
  78. audit_event_lookup(ssh_audit_event_t ev)
  79. {
  80. int i;
  81. static struct event_lookup_struct {
  82. ssh_audit_event_t event;
  83. const char *name;
  84. } event_lookup[] = {
  85. {SSH_LOGIN_EXCEED_MAXTRIES, "LOGIN_EXCEED_MAXTRIES"},
  86. {SSH_LOGIN_ROOT_DENIED, "LOGIN_ROOT_DENIED"},
  87. {SSH_AUTH_SUCCESS, "AUTH_SUCCESS"},
  88. {SSH_AUTH_FAIL_NONE, "AUTH_FAIL_NONE"},
  89. {SSH_AUTH_FAIL_PASSWD, "AUTH_FAIL_PASSWD"},
  90. {SSH_AUTH_FAIL_KBDINT, "AUTH_FAIL_KBDINT"},
  91. {SSH_AUTH_FAIL_PUBKEY, "AUTH_FAIL_PUBKEY"},
  92. {SSH_AUTH_FAIL_HOSTBASED, "AUTH_FAIL_HOSTBASED"},
  93. {SSH_AUTH_FAIL_GSSAPI, "AUTH_FAIL_GSSAPI"},
  94. {SSH_INVALID_USER, "INVALID_USER"},
  95. {SSH_NOLOGIN, "NOLOGIN"},
  96. {SSH_CONNECTION_CLOSE, "CONNECTION_CLOSE"},
  97. {SSH_CONNECTION_ABANDON, "CONNECTION_ABANDON"},
  98. {SSH_AUDIT_UNKNOWN, "AUDIT_UNKNOWN"}
  99. };
  100. for (i = 0; event_lookup[i].event != SSH_AUDIT_UNKNOWN; i++)
  101. if (event_lookup[i].event == ev)
  102. break;
  103. return(event_lookup[i].name);
  104. }
  105. void
  106. audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key)
  107. {
  108. char *fp;
  109. fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
  110. if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0)
  111. *rv = -SSH_ERR_INTERNAL_ERROR;
  112. free(fp);
  113. }
  114. void
  115. audit_unsupported(struct ssh *ssh, int what)
  116. {
  117. PRIVSEP(audit_unsupported_body(ssh, what));
  118. }
  119. void
  120. audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs)
  121. {
  122. PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()));
  123. }
  124. void
  125. audit_session_key_free(struct ssh *ssh, int ctos)
  126. {
  127. PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid()));
  128. }
  129. # ifndef CUSTOM_SSH_AUDIT_EVENTS
  130. /*
  131. * Null implementations of audit functions.
  132. * These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
  133. */
  134. /*
  135. * Called after a connection has been accepted but before any authentication
  136. * has been attempted.
  137. */
  138. void
  139. audit_connection_from(const char *host, int port)
  140. {
  141. debug("audit connection from %s port %d euid %d", host, port,
  142. (int)geteuid());
  143. }
  144. /*
  145. * Called when various events occur (see audit.h for a list of possible
  146. * events and what they mean).
  147. */
  148. void
  149. audit_event(struct ssh *ssh, ssh_audit_event_t event)
  150. {
  151. debug("audit event euid %d user %s event %d (%s)", geteuid(),
  152. audit_username(), event, audit_event_lookup(event));
  153. }
  154. /*
  155. * Called when a child process has called, or will soon call,
  156. * audit_session_open.
  157. */
  158. void
  159. audit_count_session_open(void)
  160. {
  161. debug("audit count session open euid %d user %s", geteuid(),
  162. audit_username());
  163. }
  164. /*
  165. * Called when a user session is started. Argument is the tty allocated to
  166. * the session, or NULL if no tty was allocated.
  167. *
  168. * Note that this may be called multiple times if multiple sessions are used
  169. * within a single connection.
  170. */
  171. void
  172. audit_session_open(struct logininfo *li)
  173. {
  174. const char *t = li->line ? li->line : "(no tty)";
  175. debug("audit session open euid %d user %s tty name %s", geteuid(),
  176. audit_username(), t);
  177. }
  178. /*
  179. * Called when a user session is closed. Argument is the tty allocated to
  180. * the session, or NULL if no tty was allocated.
  181. *
  182. * Note that this may be called multiple times if multiple sessions are used
  183. * within a single connection.
  184. */
  185. void
  186. audit_session_close(struct logininfo *li)
  187. {
  188. const char *t = li->line ? li->line : "(no tty)";
  189. debug("audit session close euid %d user %s tty name %s", geteuid(),
  190. audit_username(), t);
  191. }
  192. /*
  193. * This will be called when a user runs a non-interactive command. Note that
  194. * it may be called multiple times for a single connection since SSH2 allows
  195. * multiple sessions within a single connection. Returns a "handle" for
  196. * audit_end_command.
  197. */
  198. int
  199. audit_run_command(struct ssh *ssh, const char *command)
  200. {
  201. debug("audit run command euid %d user %s command '%.200s'", geteuid(),
  202. audit_username(), command);
  203. return 0;
  204. }
  205. /*
  206. * This will be called when the non-interactive command finishes. Note that
  207. * it may be called multiple times for a single connection since SSH2 allows
  208. * multiple sessions within a single connection. "handle" should come from
  209. * the corresponding audit_run_command.
  210. */
  211. void
  212. audit_end_command(struct ssh *ssh, int handle, const char *command)
  213. {
  214. debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(),
  215. audit_username(), command);
  216. }
  217. /*
  218. * This will be called when user is successfully autherized by the RSA1/RSA/DSA key.
  219. *
  220. * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key.
  221. */
  222. int
  223. audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
  224. {
  225. debug("audit %s key usage euid %d user %s fingerprint %s, result %d",
  226. host_user ? "pubkey" : "hostbased", geteuid(), audit_username(),
  227. fp, rv);
  228. }
  229. /*
  230. * This will be called when the protocol negotiation fails.
  231. */
  232. void
  233. audit_unsupported_body(struct ssh *ssh, int what)
  234. {
  235. debug("audit unsupported protocol euid %d type %d", geteuid(), what);
  236. }
  237. /*
  238. * This will be called on succesfull protocol negotiation.
  239. */
  240. void
  241. audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid,
  242. uid_t uid)
  243. {
  244. debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u",
  245. (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (long)pid,
  246. (unsigned)uid);
  247. }
  248. /*
  249. * This will be called on succesfull session key discard
  250. */
  251. void
  252. audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid)
  253. {
  254. debug("audit session key discard euid %u direction %d from pid %ld uid %u",
  255. (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
  256. }
  257. /*
  258. * This will be called on destroy private part of the server key
  259. */
  260. void
  261. audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid)
  262. {
  263. debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u",
  264. geteuid(), fp, (long)pid, (unsigned)uid);
  265. }
  266. # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
  267. #endif /* SSH_AUDIT_EVENTS */