From dfd34e3044c6dccd0ab304ea3070f2f1d2f38c08 Mon Sep 17 00:00:00 2001 From: Dante Catalfamo Date: Sun, 28 Jun 2020 18:39:13 -0400 Subject: Add info about history and basic architecture to bsd auth post --- .../posts/how-bsd-authentication-works/index.org | 65 +++++++++++++++++----- 1 file changed, 52 insertions(+), 13 deletions(-) (limited to 'content/posts/how-bsd-authentication-works/index.org') diff --git a/content/posts/how-bsd-authentication-works/index.org b/content/posts/how-bsd-authentication-works/index.org index 42e4b41..73bddf5 100644 --- a/content/posts/how-bsd-authentication-works/index.org +++ b/content/posts/how-bsd-authentication-works/index.org @@ -9,6 +9,27 @@ [[https://web.archive.org/web/20170327150148/http://www.penzin.net/bsdauth/]] +OpenBSD is quite different from many other Unix-like operating systems +in many ways, but one way which I find interesting is the +authentication system. Most systems from AIX, Solaris, and Linux to +most BSDs including MacOS use some form of a system called Pluggable +Authentication Module (PAM). The two main implementations of PAM are +[[http://www.linux-pam.org/][Linux PAM]] and [[https://www.openpam.org/][OpenPAM]]. PAM modules are created a dynamically loaded +shared objects, which communicate using a set of standard +interfaces ([[https://linux.die.net/man/3/pam][Linux-PAM]]) ([[https://www.freebsd.org/cgi/man.cgi?query=pam&apropos=0&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports&arch=default&format=html][OpenPAM]]). PAM is configured using the [[https://linux.die.net/man/5/pam.d][pam.d]] +directory and [[https://www.freebsd.org/cgi/man.cgi?query=pam.conf&sektion=5&apropos=0&manpath=FreeBSD+12.1-RELEASE+and+Ports][pam.conf]]. + +OpenBSD on the other hand uses a mechanism called BSD +Authentication. It was originally developed for a proprietary +operating system called [[https://en.wikipedia.org/wiki/BSD/OS][BSD/OS]] by [[https://en.wikipedia.org/wiki/Berkeley_Software_Design][Berkeley Software Design Inc.]], who +later donated the system. It was adopted by OpenBSD in release +2.9. BSD Auth is comparatively much simpler than PAM. Modules or, +authentication "styles", are instead stand alone applications or +scripts that communicate over IPC (=PF_LOCAL, SOCK_STREAM=, more +specifically). The program or script can then very easily isolate +itself using something like =pledge(3)= or =unveil(3)=. + + This one is pretty difficult, since there seems to be very little information about how BSD Auth works apart from the source code itself. This is my best attempt to understand the flow of BSD Auth @@ -17,8 +38,6 @@ from what I've read. All of the high level authentication functions are described in =authenticate(3)=. -~#include ~ - The highest level function, and easiest to use is =auth_userokay= which takes four character arrays as arguments, =name=, =style=, =type=, and =password=. It returns either a =0= for failure, of a @@ -160,9 +179,10 @@ case of auth style =passwd=, it would result in the path =/usr/libexec/auth/login_passwd=. Then =auth_call= is called with the struct, the path to the auth -module, the auth style, the "-s" flag followed by the service -(login, challenge, response), a double dash, the user name, and a -=NULL= character pointer. +module, the auth style, the "-s" flag followed by the service (login, +challenge, response), a double dash, the user name, and a =NULL= +character pointer. The return value of =auth_call= is ignored and a +pointer to the auth session is returned immediately afterwards. #+BEGIN_SRC c auth_call(as, path, auth_getitem(as, AUTHV_STYLE), "-s", @@ -173,14 +193,33 @@ auth_call(as, path, auth_getitem(as, AUTHV_STYLE), "-s", int auth_call(auth_session_t *as, char *path, ...) #+END_SRC -Inside of =auth_call=, a socket pair of type =PF_LOCAL, -SOCK_STREAM= is created. This is called the "back channel", and is -used to communicate between with the authentication module. The -process then forks, calling ~execve(path, argv, auth_environ)~, -where the =argv= is everything after =path= in the =auth_call= -arguments. Any =authopts= set in the auth session are also passed -as arguments in the format =-v opt1 -v opt2 -v opt3=, -etc. =auth_environ= is defined at the top of the file as +<> + +--- +note: In the man page auth_subr it says +#+begin_quote +path The full path name of the login script to run. The call will + fail if path does not pass the requirements of the secure_path(3) + function. +#+end_quote +However I don't see this enforced anywhere, I even wrote a small test +script to prove that's the case on =vfwall ~/authtest=. + +The manpage also says the path is limited to =/bin/= and =/usr/bin=, +which is also not the case. + +Ask jcs about the file descriptor situation, I don't understand it +after reading both the man page and source. +--- + +Inside of =auth_call=, a socket pair of type =PF_LOCAL, SOCK_STREAM= +is created. This is called the "back channel", and is used to +communicate with the authentication module. The process then forks, +calling ~execve(path, argv, auth_environ)~, where the =argv= is +everything after =path= in the =auth_call= arguments. Any =authopts= +set in the auth session are also passed as arguments in the format =-v +opt1 -v opt2 -v opt3=, etc. =auth_environ= is defined at the top of +the file as #+BEGIN_SRC c static char *auth_environ[] = { -- cgit v1.2.3