From 118b0019658890837ab8e19608ce0779cb6f4d9a Mon Sep 17 00:00:00 2001
From: Dante Catalfamo
Date: Tue, 7 Jul 2020 22:28:28 -0400
Subject: Move WIP posts to WIP folders

---
 .../WIP-how-bsd-authentication-works/graph.dot     |  67 +++
 .../WIP-how-bsd-authentication-works/index.org     | 473 +++++++++++++++++++++
 content/posts/WIP-how-this-blog-works.org          | 239 +++++++++++
 .../WIP-installing-openbsd-on-pcengines/index.org  |  87 ++++
 .../posts/how-bsd-authentication-works/graph.dot   |  67 ---
 .../posts/how-bsd-authentication-works/index.org   | 473 ---------------------
 content/posts/how-this-blog-works.org              | 239 -----------
 content/posts/openbsd-dhcp-server/index.org        |   8 -
 8 files changed, 866 insertions(+), 787 deletions(-)
 create mode 100644 content/posts/WIP-how-bsd-authentication-works/graph.dot
 create mode 100644 content/posts/WIP-how-bsd-authentication-works/index.org
 create mode 100644 content/posts/WIP-how-this-blog-works.org
 create mode 100644 content/posts/WIP-installing-openbsd-on-pcengines/index.org
 delete mode 100644 content/posts/how-bsd-authentication-works/graph.dot
 delete mode 100644 content/posts/how-bsd-authentication-works/index.org
 delete mode 100644 content/posts/how-this-blog-works.org
 delete mode 100644 content/posts/openbsd-dhcp-server/index.org

(limited to 'content/posts')

diff --git a/content/posts/WIP-how-bsd-authentication-works/graph.dot b/content/posts/WIP-how-bsd-authentication-works/graph.dot
new file mode 100644
index 0000000..6414b11
--- /dev/null
+++ b/content/posts/WIP-how-bsd-authentication-works/graph.dot
@@ -0,0 +1,67 @@
+digraph G {
+    subgraph cluster_authenticate {
+        label = "authenticate.c"
+        auth_userokay;
+        auth_usercheck;
+        auth_verify;
+    }
+
+    subgraph cluster_auth_subr {
+        label = "auth_subr.c"
+        auth_open;
+        auth_call;
+        auth_close;
+        // auth_setitem;
+        // auth_setdata;
+        // auth_setopts;
+        auth_set[label="auth_set*"];
+        auth_setstate;
+        // _auth_spool;
+    }
+
+    subgraph cluster_login_cap {
+        label = "libc/login_cap.c"
+        login_getclass
+        login_getstyle
+    }
+
+    subgraph cluster_getpwent {
+        label = "libc/getpwent.c"
+        getpwnam_r;
+    }
+
+    subgraph cluster_exec {
+        login[label="login_*"];
+        execve;
+    }
+
+
+    start -> auth_userokay;
+    auth_userokay -> auth_usercheck;
+    auth_usercheck -> getpwnam_r;
+    auth_usercheck -> login_getclass;
+    auth_usercheck -> login_getstyle;
+    // if password given
+    auth_usercheck -> auth_open;
+    // auth_usercheck -> auth_setitem;
+    // auth_usercheck -> auth_setdata;
+    auth_usercheck -> auth_set;
+    // fi
+    auth_usercheck -> auth_verify;
+
+    auth_verify -> auth_setstate;
+    auth_verify -> auth_call;
+
+    auth_call -> execve[label="fork()"];
+    // auth_call -> _auth_spool;
+
+    execve -> login;
+    login -> auth_call[label="back channel"];
+    // login -> _auth_spool[label="back channel"];
+
+
+    // auth_usercheck -> { auth_setitem auth_setdata auth_setopts }
+
+    // auth_call -> auth_userokay;
+    auth_userokay -> auth_close;
+}
diff --git a/content/posts/WIP-how-bsd-authentication-works/index.org b/content/posts/WIP-how-bsd-authentication-works/index.org
new file mode 100644
index 0000000..4126284
--- /dev/null
+++ b/content/posts/WIP-how-bsd-authentication-works/index.org
@@ -0,0 +1,473 @@
+#+TITLE: How BSD Authentication Works
+#+DATE: 2020-06-26T18:31:36-04:00
+#+DRAFT: true
+#+DESCRIPTION:
+#+TAGS[]: openbsd
+#+KEYWORDS[]: openbsd
+#+SLUG:
+#+SUMMARY:
+#+SHOWTOC: true
+
+[[https://web.archive.org/web/20170327150148/http://www.penzin.net/bsdauth/]]
+* History
+
+  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]] and [[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=,
+  specifically). The program or script has no ability to interfere
+  with the parent and can very easily revoke permissions using
+  [[https://man.openbsd.org/pledge][=pledge(2)=]] or [[https://man.openbsd.org/unveil][=unveil(2)=]]. The BSD Authentication system of
+  configured through [[https://man.openbsd.org/login.conf][=login.conf(5)=]].
+
+* Why
+
+  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
+  from what I've read.
+
+* BSD Auth Modules
+
+  These programs or scripts are located in =/usr/libexec/auth/= with the
+  naming convention =login_<style>=. They take arguments in the form of
+
+  #+BEGIN_SRC shell
+  login_<style> [-s service] [-v key=value] user [class]
+  #+END_SRC
+
+  - =<style>= is the authentication method. This could be =passwd=,
+    =radius=, =skey=, =yubikey=, etc. There's more information about
+    available styles in [[https://man.openbsd.org/login.conf][=login.conf(5)=]] under the [[https://man.openbsd.org/login.conf#AUTHENTICATION][=AUTHENTICATION=]]
+    header.
+  - =service= is the service type. Typically authentication methods will
+    accept one of three values here, =login=, =challenge=, or
+    =response=. =login= is the default if it's not specified, and is
+    usually the right choice. Read the style's man page for details.
+  - =-v key=value= is an optional argument. There is no limit to the
+    number of =-v= arguments. This is used to pass extra data to the
+    program under certain circumstances.
+  - =user= is the name of the user to be authenticated.
+  - =class= is optional and specifies the class of the user to be
+    authenticated.
+
+  =login= and =su= pass in extra data as =-v= flags.
+
+  #+CAPTION: Taken from [[https://man.openbsd.org/login.conf][=login.conf(5)=]]
+  #+BEGIN_SRC
+  The login(1) program provides the following through the -v option:
+
+     auth_type       The type of authentication to use.
+
+     fqdn            The hostname provided to login by the -h option.
+
+     hostname        The name login(1) will place in the utmp file for the
+                     remote hostname.
+
+     local_addr      The local IP address given to login(1) by the -L option.
+
+     lastchance      Set to "yes" when a user's password has expired but the
+                     user is being given one last chance to login and update
+                     the password.
+
+     login           This is a new login session (as opposed to a simple
+                     identity check).
+
+     remote_addr     The remote IP address given to login(1) by the -R option.
+
+     style           The style of authentication used for this user (see
+                     approval scripts below).
+
+     The su(1) program provides the following through the -v option:
+
+     wheel           Set to either "yes" or "no" to indicate if the user is in
+                     group wheel when they are trying to become root.  Some
+                     authentication types require the user to be in group
+                     wheel when using the su(1) program to become super user.
+  #+END_SRC
+
+  The auth module communicates with its caller through file descriptor 3.
+
+* Documentation
+
+  All of the high level authentication functions are described in
+  [[https://man.openbsd.org/authenticate][=authenticate(3)=]], with the lower level functions being described in
+  [[https://man.openbsd.org/auth_subr][=auth_subr(3)=]].
+
+* auth_userokay
+
+  The highest level function, and easiest to use is =auth_userokay=. It
+  takes four character arrays as arguments, =name=, =style=, =type=, and
+  =password=. It returns either a =0= for failure, of a non-zero value
+  for success.
+
+  This function lives inside =/lib/libc/gen/authenticate.c=
+
+  #+BEGIN_SRC c
+  int auth_userokay(char *name, char *style, char *type, char *password);
+  #+END_SRC
+
+  - =name= is the name of the user to be authenticated
+  - =style= is the login method to be used
+    - If =style= is =NULL=, the user's default login style will be
+      used. By default this is =passwd= on normal accounts.
+    - The style can be one of the installed authentication methods, like
+      =passwd=, =radius=, =skey=, =yubikey=, etc.
+    - There's more information about available styles in =login.conf(5)=
+    - Styles can also be installed through BSD Auth module packages
+  - =type= is the authentication type
+    - Types are defined in =login.conf= and define a group of allowed
+      auth styles
+    - If =type= is =NULL=, use the auth type for the user's login
+      class. The default type is =auth-default=, which allows
+      =psaswd= and =skey= auth methods.
+    - There's more information about how to add methods in =login.conf(5)=
+  - =password= is the password to test
+    - If =password= is =NULL=, then the user is interactively
+      prompted. This is required for auth styles using
+      challenge-response methods.
+    - If =password= is specified, then it's non-interactively tested
+
+  =auth_userokay= is just a wrapper around =auth_usercheck=, which
+  returns a finished auth session of type =auth_session_t=. It closes
+  the auth session using =auth_close= and returns the value returned
+  from closing.
+
+* auth_session_t
+
+  #+BEGIN_SRC c
+  struct auth_session_t {
+      char    *name;                 /* name of use being authenticated */
+      char    *style;                /* style of authentication used */
+      char    *class;                /* class of user */
+      char    *service;              /* type of service being performed */
+      char    *challenge;            /* last challenge issued */
+      int     flags;                 /* see below */
+      struct  passwd *pwd;           /* password entry for user */
+      struct  timeval now;           /* time of authentication */
+
+      int     state;                 /* authenticated state */
+
+      struct  rmfiles *rmlist;       /* list of files to remove on failure */
+      struct  authopts *optlist;     /* list of options to scripts */
+      struct  authdata *data;        /* additional data to send to scripts */
+
+      char    spool[MAXSPOOLSIZE];   /* data returned from login script */
+      int     index;                 /* how much returned thus far */
+
+      int     fd;                    /* connection to authenticator */
+
+      va_list ap0;                   /* argument list to auth_call */
+      va_list ap;                    /* additional arguments to auth_call */
+  };
+  #+END_SRC
+
+  Where =authdata=, =authopts=, and =rmfiles= are defined as
+
+  #+BEGIN_SRC c
+  struct rmfiles {
+      struct rmfiles  *next;
+      char            *file;
+  };
+
+  struct authopts {
+      struct authopts *next;
+      char            *opt;
+  };
+
+  struct authdata {
+      struct  authdata *next;
+      void    *ptr;
+      size_t   len;
+  };
+  #+END_SRC
+
+** auth_setdata
+
+** auth_setitem
+
+** auth_setoption
+
+** auth_setstate
+* auth_open
+
+  The =auth_open= function is used by several functions to create a
+  new auth session. It allocates an =auth_session_t= struct on the
+  heap, sets its default =service= to =login=, and it's =fd= to =-1=,
+  and returns the pointer.
+
+* auth_usercheck
+
+  #+BEGIN_SRC c
+  auth_session_t *auth_usercheck(char *name, char *style, char *type, char *password)
+  #+END_SRC
+
+  =auth_usercheck= checks the user name against the passwd db. It also
+  checks the login class against the =login.conf= db, along with
+  confirming the login styles available.
+
+  If the password is non-=NULL=, then it creates a new session using
+  =auth_open=. With the new session, =auth_usercheck= calls (with =as=
+  as the session struct)
+
+  #+BEGIN_SRC c
+  auth_setitem(as, AUTHV_SERVICE, "response");
+  auth_setdata(as, "", 1);
+  auth_setdata(as, password, strlen(password) + 1);
+  #+END_SRC
+
+  setting the service protocol to =response=, adding an empty line to
+  the session data, then adding the password as data. If the password is
+  =NULL=, it sets the =auth_session_t= pointer to =NULL=. It then passes
+  the user name, style, login class, and =NULL= char pointer to
+  =auth_verify=. The last two variables are received as variable
+  arguments. It then returns the auth session pointer the call
+  returns.
+
+* auth_verify
+
+  #+BEGIN_SRC c
+  auth_session_t *auth_verify(auth_session_t *as, char *style, char *name, ...)
+  #+END_SRC
+
+  =auth_verify= creates an auth session using =auth_open= if =as= is
+  =NULL=. It then sets the user name and style of the session, if the
+  respective arguments are non-=NULL=. It then copies its variable
+  arguments to the auth session's =va_list ap=, which is used inside
+  of =auth_call=.
+
+  After that it constructs the path of the authentication module by
+  combining =_PATH_AUTHPROG=, which is defined in =login_cap.h= as
+  =/usr/libexec/auth/login_=, and the authentication style. For the
+  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. 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",
+      auth_getitem(as, AUTHV_SERVICE), "--", name, (char *)NULL);
+  #+END_SRC
+
+* auth_call
+
+  #+BEGIN_SRC c
+  int auth_call(auth_session_t *as, char *path, ...)
+  #+END_SRC
+
+  <<here>>
+
+  ---
+  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[] = {
+      "PATH=" _PATH_DEFPATH,
+      "SHELL=" _PATH_BSHELL,
+      NULL,
+  };
+  #+END_SRC
+
+  Where both constants are defined in =paths.h= as
+
+  #+BEGIN_SRC c
+  #define	_PATH_DEFPATH	"/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin"
+  #define	_PATH_BSHELL	"/bin/sh"
+  #+END_SRC
+
+
+  The =exec='d process then listens on FD 3, which is one half of the
+  =sockpair= that was created earlier.
+
+  In the non-exec'd process, first the contents of the auth session's
+  =*data= are read in one at a time.
+
+  The data received through the back channel is then put into the
+  =spool= of the auth session using =_auth_spool(as, pfd[0])=. After
+  that the spooled data is scanned for key words defined in
+  =login_cap.h=.
+
+  #+BEGIN_SRC c
+  #define BI_AUTH         "authorize"         /* Accepted authentication */
+  #define BI_REJECT       "reject"            /* Rejected authentication */
+  #define BI_CHALLENGE    "reject challenge"  /* Reject with a challenge */
+  #define BI_SILENT       "reject silent"     /* Reject silently */
+  #define BI_REMOVE       "remove"            /* remove file on error */
+  #define BI_ROOTOKAY     "authorize root"    /* root authenticated */
+  #define BI_SECURE       "authorize secure"  /* okay on non-secure line */
+  #define BI_SETENV       "setenv"            /* set environment variable */
+  #define BI_UNSETENV     "unsetenv"          /* unset environment variable */
+  #define BI_VALUE        "value"             /* set local variable */
+  #define BI_EXPIRED      "reject expired"    /* account expired */
+  #define BI_PWEXPIRED    "reject pwexpired"  /* password expired */
+  #define BI_FDPASS       "fd"                /* child is passing an fd */
+  #+END_SRC
+
+  The [[https://man.openbsd.org/login.conf][=login.conf(5)=]] man page once again goes into greater detail on
+  these values.
+
+  #+BEGIN_SRC
+  authorize  The user has been authorized.
+
+  authorize secure
+             The user has been authorized and root should be allowed to
+             login even if this is not a secure terminal.  This should only
+             be sent by authentication styles that are secure over insecure
+             lines.
+
+  reject     Authorization is rejected.  This overrides any indication that
+             the user was authorized (though one would question the wisdom
+             in sending both a reject and an authorize command).
+
+  reject challenge
+             Authorization was rejected and a challenge has been made
+             available via the value challenge.
+
+  reject silent
+             Authorization is rejected, but no error messages should be
+             generated.
+
+  remove file
+             If the login session fails for any reason, remove file before
+             termination.
+
+  setenv name value
+             If the login session succeeds, the environment variable name
+             should be set to the specified value.
+
+  unsetenv name
+             If the login session succeeds, the environment variable name
+             should be removed.
+
+  value name value
+             Set the internal variable name to the specified value.  The
+             value should only contain printable characters.  Several \
+             sequences may be used to introduce non printing characters.
+             These are:
+
+             \n      A newline.
+
+             \r      A carriage return.
+
+             \t      A tab.
+
+             \xxx    The character represented by the octal value xxx.  The
+                     value may be one, two, or three octal digits.
+
+             \c      The string is replaced by the value of c.  This allows
+                     quoting an initial space or the \ character itself.
+
+
+             The following values are currently defined:
+
+             challenge
+                     See section on challenges below.
+
+             errormsg
+                     If set, the value is the reason authentication failed.
+                     The calling program may choose to display this when
+                     rejecting the user, but display is not required.
+
+  #+END_SRC
+
+
+  It is looking for lines that start with either =BI_AUTH=
+  (=authorize=), or =BI_REJECT= (=reject=). If the line is still longer,
+  it continues to scan for any other qualifiers such as =pwexpired= or
+  =silent=. The struct's =state= is set to one using the =AUTH_= values
+  from =login_cap.h= accordingly.
+
+  #+BEGIN_SRC c
+  /*
+   * bits which can be returned by authenticate()/auth_scan()
+   */
+  #define  AUTH_OKAY       0x01            /* user authenticated */
+  #define  AUTH_ROOTOKAY   0x02            /* authenticated as root */
+  #define  AUTH_SECURE     0x04            /* secure login */
+  #define  AUTH_SILENT     0x08            /* silent rejection */
+  #define  AUTH_CHALLENGE  0x10            /* a challenge was given */
+  #define  AUTH_EXPIRED    0x20            /* account expired */
+  #define  AUTH_PWEXPIRED  0x40            /* password expired */
+  #+END_SRC
+
+** _auth_spool
+
+** _recv_fd
+
+* auth_close
+  =auth_close= is the function responsible for cleaning up the session
+  and taking care of the values returned though the back channel.
+
+  It first sets the environment variables returned through the back
+  channel by passing the auth session to =auth_setenv=. It then goes
+  through the =rmlist= of the session, deleting the files if the
+  session reported a failure. It then zeroes out all sensitive
+  information, and frees the various structs associated with the current
+  =auth_session_t=, and then the session itself. Finally it returns
+  the session's state =&='ed with =AUTH_ALLOW=.
+* grapgh?
+# Setting env on auth_close(as)
+# partual rewrite below
+
+The call graph for =auth_userokay= looks something like this:
+
+#+BEGIN_SRC c
+int auth_userokay(char *name, char *style, char *type, char *password)
+#+END_SRC
+
+calls ~auth_usercheck~ and then calls ~auth_close~ on the returned
+~auth_session_t~. The value returned from ~auth_close~ is then
+returned.
+
+#+BEGIN_SRC c
+auth_session_t *auth_usercheck(char *name, char *style, char *type, char *password)
+#+END_SRC
+
+Validates the checks that the user exists, gets the user's login
+class, verifies the auth type, and that the auth style can be used.
+
+It creates an auth session struct.
+
+If the password is provided it sets the service type to =response=,
+and adds the adds the password to the auth data. Otherwise it
+leaves it empty.
diff --git a/content/posts/WIP-how-this-blog-works.org b/content/posts/WIP-how-this-blog-works.org
new file mode 100644
index 0000000..80fa1ca
--- /dev/null
+++ b/content/posts/WIP-how-this-blog-works.org
@@ -0,0 +1,239 @@
+#+TITLE: Creating Self-Hosted Hugo Blog on OpenBSD
+#+DATE: 2020-06-17T21:03:26-04:00
+#+DRAFT: true
+#+DESCRIPTION:
+#+TAGS[]: hugo openbsd
+#+KEYWORDS[]:
+#+SLUG:
+#+SUMMARY:
+#+SHOWTOC: true
+
+When creating this blog, there were a couple of factors I kept in mind
+while trying to figure out how I was going to set it up:
+
+- Simple
+- Version controlled
+- Easy to host on OpenBSD
+- Minimal maintenance
+- Good integration with Emacs
+# more
+That's how I came up with what I currently use. Let's walk through how
+it works.
+
+* Framework
+
+  The blog engine is [[https://gohugo.io/][hugo]], a static site generator. I chose this over
+  something dynamic like wordpress for several reasons.
+
+  First of all, it's very easy to manage, blog posts are just simple
+  files written in one of the markup languages hugo supports. Being
+  statically generated is also a massive advantage in terms of
+  maintenance. With something like wordpress, you have to be careful to
+  keep your site and plugins up to date.
+
+  Since there's no dynamic content generation or database involved with
+  hugo, the attack surface is dramatically decreased. No possibility for
+  SQL injection, PHP RATs, accidental shell access, or hacked
+  credentials. The entire site is generated using a single command after
+  a new post is created, and then moved to the web server's root
+  directory.
+
+  Being all flat files also means the entire thing can very easily be
+  tracked using =git= (or maybe [[https://gameoftrees.org/][got]], eventually), in fact that's the
+  recommended way to use hugo. There's no fear I'll accidentally delete
+  something, as I can always go back to a previous commit and restore
+  it.
+
+  Since hugo is written in go, it's trivial to compile on OpenBSD, and
+  is actually available directly from the OpenBSD package manager right
+  out of the gate.
+
+  Maybe the most important thing to be however, is that hugo natively
+  supports org-mode markup. I write all my notes, both personal and work
+  related, in org-mode. It makes converting my notes into blog posts
+  really easy. It also lets me leverage my existing Emacs setup, which
+  comes in handy often. While it's not very well documented, since
+  org-mode markup is a bit of a second class citizen in the hugo world,
+  it's pretty easy to figure out.
+
+* Prerequisites
+
+  This can be hosted on a very cheap VPS since it only has to serve
+  static pages. For OpenBSD hosting I would recommend either [[https://www.vultr.com/][Vultr]] or
+  [[https://openbsd.amsterdam/][OpenBSD Amsterdam]].
+
+** Server
+  The only thing that's required on the host server is =git=, although
+  you could even get away without that if you chose to host your git
+  repository elsewhere, like on github.
+
+  #+BEGIN_SRC shell
+  pkg_add git
+  #+END_SRC
+
+** Local machine
+  On the local machine you'll need both =git= and =rsync=. Both might
+  already be installed depending on the system you're on. If not,
+  check your package manager for details on how to install them. In
+  the case of Ubuntu or Debian it would be
+
+  #+BEGIN_SRC shell
+  sudo apt install git rsync
+  #+END_SRC
+
+  or for Fedora
+
+  #+BEGIN_SRC shell
+  sudo dnf install git rsync
+  #+END_SRC
+
+* Version Control
+
+  I wanted to try to keep things as simple as possible for this. The
+  "origin" for the blog is simply a bare git repository in the =blog=
+  user's home directory.
+
+** Setting up the blog user
+
+   First I set up the blog user
+   #+BEGIN_SRC shell
+   useradd -m blog
+   #+END_SRC
+
+   I then placed my public SSH key in its =authorized_keys= file
+
+   #+BEGIN_SRC shell
+   mkdir -m 700 /home/blog/.ssh
+   cp /root/.ssh/authorized_keys /home/blog/.ssh/
+   chown -R blog:blog /home/blog
+   #+END_SRC
+
+   I then logged in as the blog user and initialize the bare git
+   repository.
+
+   #+BEGIN_SRC shell
+   su blog
+   cd   # cd with no arguments goes to home directory
+   git init --bare blog.git
+   #+END_SRC
+
+** Cloning the repository
+
+   Cloning the repository onto my local machine is very easy at this
+   point. As long as my private keys are in the =blog= user's
+   =authorized_keys=, git will take care of the rest.
+
+   #+BEGIN_SRC shell
+   # on my local machine
+   git clone blog@lambda.cx:blog.git
+   #+END_SRC
+
+   I can now work on the blog as I would any other git repository,
+   pulling with =git pull= and pushing with =git push=.
+
+* Web Server
+
+  Since this blog is going to be hosted on OpenBSD, we don't need to
+  install a web server, as it already comes with one built in.
+
+  Setting up =httpd= couldn't be easier, the configuration syntax is
+  very straight forward. If you would like to see a full breakdown of
+  the options available, check out the man page with =man
+  httpd.conf=. The example configuration in =/etc/examples/httpd.conf=
+  is also a good starting point.
+
+  In this case the simplest configuration would be as follows
+
+  # js chosen for prism.js syntax highlighting
+  #+BEGIN_SRC js
+  server "blog.lambda.cx" {
+      listen on * port 80
+      root "/htdocs/blog.lambda.cx"
+  }
+  #+END_SRC
+
+  Despite how it looks, the =htdocs= folder doesn't reside in the
+  system root (=/=) directory. It actually lives in =/var/www/htdocs=,
+  and only appears that way because =httpd= gets automatically
+  =chroot='ed in =/var/www/= for security reasons.
+
+  Finally we start and enable =httpd= using =rcctl=
+
+  #+BEGIN_SRC shell
+  rcctl enable httpd
+  rcctl start httpd
+  #+END_SRC
+
+
+  For more information about how to set up SSL with Let's Encrypt,
+  check out [[{{< ref "posts/letsencrypt-on-openbsd" >}}][this post]].
+
+* Using Hugo
+
+  There's not much to say here. Hugo's [[https://gohugo.io/][website]] has good documentation
+  on how to get started creating a blog. I'll be covering the
+  intricacies of using org-mode with hugo in the future.
+
+* Deployment
+
+  The system used to deploy this blog is incredibly simple, involving
+  only =rsync=, =hugo=, and a small shell script.
+
+** Server
+  First you have to allow the =blog= user to write to the website
+  root. We'll do this by making it the owner of
+  =/var/www/htdocs/blog.lambda.cx=.
+
+  #+BEGIN_SRC shell
+  chown -R blog /var/www/htdocs/blog.lambda.cx
+  #+END_SRC
+
+** Local machine
+
+   This is the script used to deploy the website. It's placed in the
+   root of the hugo git repository.
+
+   #+BEGIN_SRC shell
+   #!/bin/sh
+   set -e
+
+   cd '$(dirname "$0")'
+   hugo
+   rsync -va --progress --delete --rsync-path="/usr/bin/openrsync" public/ blog@lambda.cx:/var/www/htdocs/lambda.cx/blog
+   #+END_SRC
+
+   Going through it line by line:
+
+   - ~set -e~ Tells the shell to exit if any commands fail instead of
+     continuing execution. If ~hugo~ has a problem and exits with an
+     error, don't sync with the server.
+   - ~cd '$(dirname "$0")'~ Changes to the script's directory. This is
+     used in case you're running it from somewhere else.
+   - ~hugo~ Compile the website into static files located in the
+     =public= directory.
+   - ~rsync -va --progress --rsync-path="/usr/bin/openrsync" public/
+     blog@lambda.cx:/var/www/htdocs/lambda.cx/blog~ This one is bigger
+     so I'll break it down.
+     - =rsync= A command that synchronizes files between two directories
+     - =-v= Be verbose, this is optional but I like it
+     - =-a= Stands for "archive": copy recursively, keep
+       permissions, etc. See the =rsync= man page if you're curious.
+     - =--progress= Show progress, also optional
+     - =--delete= Removed files on the server that no longer exist on
+       the client
+     - ~--rsync-path="/usr/bin/openrsync"~ This line is very important
+       for OpenBSD servers. OpenBSD has its own =rsync= implementation
+       called =openrsync=. Without this argument, =rsync= will connect
+       to the server, see that the =rsync= command doesn't exist, and
+       fail.
+     - =public/= Specify which folder we want to sync. The trailing
+       =/= is important. Without it =rsync= will copy the folder
+       instead of the folder's contents, which is what we want.
+     - =blog@lambda.cx:/var/www/htdocs/lambda.cx/blog= Login to user
+       =blog= on server =lambda.cx=, syncing files with the
+       =/var/www/htdocs/lambda.cx/blog= directory.
+
+   The reason to use =rsync= here instead of something like =scp= is
+   that =rsync= won't upload files it doesn't need to, so if 3/4 of
+   the files didn't change when you updated the blog, it won't waste
+   time re-uploading them.
diff --git a/content/posts/WIP-installing-openbsd-on-pcengines/index.org b/content/posts/WIP-installing-openbsd-on-pcengines/index.org
new file mode 100644
index 0000000..11a0436
--- /dev/null
+++ b/content/posts/WIP-installing-openbsd-on-pcengines/index.org
@@ -0,0 +1,87 @@
+#+TITLE: Installing OpenBSD on a PC Engines APU2
+#+DATE: 2020-07-07T21:21:18-04:00
+#+DRAFT: false
+#+DESCRIPTION:
+#+TAGS[]: openbsd pcengines
+#+KEYWORDS[]: openbsd pcengines
+#+SLUG:
+#+SUMMARY:
+
+I recently purchased a new PC Engines APU2E4 to use as a home
+router. I purchased the kit, which includes the board, case, and power
+supply from https://corpshadow.biz/. I also ordered the DB9F to USB
+adapter (Silicon Labs CP2104), so I don't need to get a separate null
+modem connector.  They're the only PC Engines distributor in Canada
+listed on the PC Engines website. I had a great experience with
+CorpShadow, they also sell a lot of other small single board PCs, so
+check them out if you live in Canada.
+
+I also ordered a 128 GB mSATA SSD, as it significantly out-performs
+any SD card you might put in the machine. While it's not necessary,
+and an SD card would be much cheaper, I find the improved read and
+write speeds are worth it. I got it from Canada Computers, as they
+seemed to have the best price on one. mSATA SSDs are surprisingly not
+as common as one might think on PC parts websites. And even when they
+have one, I've found most sites will only carry one brand.
+
+The first step was to install the heat sync onto the CPU. This is
+described on the PC Engines website. The heat sync is effectively just
+a block of aluminum that you use to thermally bridge the CPU to the
+enclosure. They're connected with, what I assume is, thermally
+conductive double sided tape, which they provide for you.
+
+After the CPU is stuck to the enclosure using the tape and the board
+is screwed in place, I installed the mSATA SSD into the first
+expansion slot labelled =mSATA=. Then I screwed the top of the case
+on, plugged the antenna holes with the provided rubber stoppers, and
+screwed the bolts back on the RS232 port. These things are really easy
+to put together!
+
+I downloaded the AMD64 =installXX.fs= image from the OpenBSD website and
+burned it onto a spare USB drive I had lying around using =dd=. After
+that I inserted the drive into the USB port on the APU2.
+
+I then plugged one end of the DB9F end of the serial adapter into the
+APU2, and the USB end into my PC. My desktop runs Fedora, so I had to
+install the =cu= utility using =sudo dnf install cu=. I then dialed it
+up using the serial adapter with the command =sudo cu -s 115200 -l
+/dev/ttyUSB0=.
+
+I plugged in the power connector into the APU2, and I saw the boot
+info in my terminal! It's really cool that these things use SeaBIOS
+and Coreboot.
+
+It automatically booted from the USB device, and I got dropped into
+the OpenBSD =boot>= prompt. Instead of pressing enter like normal, I
+entered
+#+BEGIN_SRC
+boot> stty com0 115200
+boot> set tty com0
+#+END_SRC
+
+The first command sets the baud rate for the serial connection. The
+second command tells the OpenBSD installer to set the default TTY to
+the serial port =COM0=. Without these, the machine will start to boot,
+fail to find an output, and reboot.
+
+After that the installation went along as a normal install would. I
+wasn't connected to the internet, but I already knew what IP was
+assigning it, so I entered that manually when asked. I also installed
+the sets from the USB. To do that, when prompted for the location of
+the sets, type =disk=, when asked if it's already mounted type =no=,
+then select the default partition and path, and continue without
+signature. The signature isn't required since it's part of the install
+media (assuming you verified the signature of the install media).
+
+After the install was done, I moved it to where I will be leaving it
+to run, plugged in the power and ethernet, and SSH'd in. At that point
+I ran =fw_update= to pull in any extra firmware I might need, and
+=syspatch= to keep myself up to date with security patches.
+
+I kept the serial adapter connected and plugged it into another
+machine I have right next to it, so if I ever have any trouble
+booting, I can always SSH into the other machine and dial into the
+serial connector to work things out without having to physically plug
+the APU2 into my laptop.
+
+Finally I added the OpenBSD sticker!
diff --git a/content/posts/how-bsd-authentication-works/graph.dot b/content/posts/how-bsd-authentication-works/graph.dot
deleted file mode 100644
index 6414b11..0000000
--- a/content/posts/how-bsd-authentication-works/graph.dot
+++ /dev/null
@@ -1,67 +0,0 @@
-digraph G {
-    subgraph cluster_authenticate {
-        label = "authenticate.c"
-        auth_userokay;
-        auth_usercheck;
-        auth_verify;
-    }
-
-    subgraph cluster_auth_subr {
-        label = "auth_subr.c"
-        auth_open;
-        auth_call;
-        auth_close;
-        // auth_setitem;
-        // auth_setdata;
-        // auth_setopts;
-        auth_set[label="auth_set*"];
-        auth_setstate;
-        // _auth_spool;
-    }
-
-    subgraph cluster_login_cap {
-        label = "libc/login_cap.c"
-        login_getclass
-        login_getstyle
-    }
-
-    subgraph cluster_getpwent {
-        label = "libc/getpwent.c"
-        getpwnam_r;
-    }
-
-    subgraph cluster_exec {
-        login[label="login_*"];
-        execve;
-    }
-
-
-    start -> auth_userokay;
-    auth_userokay -> auth_usercheck;
-    auth_usercheck -> getpwnam_r;
-    auth_usercheck -> login_getclass;
-    auth_usercheck -> login_getstyle;
-    // if password given
-    auth_usercheck -> auth_open;
-    // auth_usercheck -> auth_setitem;
-    // auth_usercheck -> auth_setdata;
-    auth_usercheck -> auth_set;
-    // fi
-    auth_usercheck -> auth_verify;
-
-    auth_verify -> auth_setstate;
-    auth_verify -> auth_call;
-
-    auth_call -> execve[label="fork()"];
-    // auth_call -> _auth_spool;
-
-    execve -> login;
-    login -> auth_call[label="back channel"];
-    // login -> _auth_spool[label="back channel"];
-
-
-    // auth_usercheck -> { auth_setitem auth_setdata auth_setopts }
-
-    // auth_call -> auth_userokay;
-    auth_userokay -> auth_close;
-}
diff --git a/content/posts/how-bsd-authentication-works/index.org b/content/posts/how-bsd-authentication-works/index.org
deleted file mode 100644
index 4126284..0000000
--- a/content/posts/how-bsd-authentication-works/index.org
+++ /dev/null
@@ -1,473 +0,0 @@
-#+TITLE: How BSD Authentication Works
-#+DATE: 2020-06-26T18:31:36-04:00
-#+DRAFT: true
-#+DESCRIPTION:
-#+TAGS[]: openbsd
-#+KEYWORDS[]: openbsd
-#+SLUG:
-#+SUMMARY:
-#+SHOWTOC: true
-
-[[https://web.archive.org/web/20170327150148/http://www.penzin.net/bsdauth/]]
-* History
-
-  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]] and [[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=,
-  specifically). The program or script has no ability to interfere
-  with the parent and can very easily revoke permissions using
-  [[https://man.openbsd.org/pledge][=pledge(2)=]] or [[https://man.openbsd.org/unveil][=unveil(2)=]]. The BSD Authentication system of
-  configured through [[https://man.openbsd.org/login.conf][=login.conf(5)=]].
-
-* Why
-
-  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
-  from what I've read.
-
-* BSD Auth Modules
-
-  These programs or scripts are located in =/usr/libexec/auth/= with the
-  naming convention =login_<style>=. They take arguments in the form of
-
-  #+BEGIN_SRC shell
-  login_<style> [-s service] [-v key=value] user [class]
-  #+END_SRC
-
-  - =<style>= is the authentication method. This could be =passwd=,
-    =radius=, =skey=, =yubikey=, etc. There's more information about
-    available styles in [[https://man.openbsd.org/login.conf][=login.conf(5)=]] under the [[https://man.openbsd.org/login.conf#AUTHENTICATION][=AUTHENTICATION=]]
-    header.
-  - =service= is the service type. Typically authentication methods will
-    accept one of three values here, =login=, =challenge=, or
-    =response=. =login= is the default if it's not specified, and is
-    usually the right choice. Read the style's man page for details.
-  - =-v key=value= is an optional argument. There is no limit to the
-    number of =-v= arguments. This is used to pass extra data to the
-    program under certain circumstances.
-  - =user= is the name of the user to be authenticated.
-  - =class= is optional and specifies the class of the user to be
-    authenticated.
-
-  =login= and =su= pass in extra data as =-v= flags.
-
-  #+CAPTION: Taken from [[https://man.openbsd.org/login.conf][=login.conf(5)=]]
-  #+BEGIN_SRC
-  The login(1) program provides the following through the -v option:
-
-     auth_type       The type of authentication to use.
-
-     fqdn            The hostname provided to login by the -h option.
-
-     hostname        The name login(1) will place in the utmp file for the
-                     remote hostname.
-
-     local_addr      The local IP address given to login(1) by the -L option.
-
-     lastchance      Set to "yes" when a user's password has expired but the
-                     user is being given one last chance to login and update
-                     the password.
-
-     login           This is a new login session (as opposed to a simple
-                     identity check).
-
-     remote_addr     The remote IP address given to login(1) by the -R option.
-
-     style           The style of authentication used for this user (see
-                     approval scripts below).
-
-     The su(1) program provides the following through the -v option:
-
-     wheel           Set to either "yes" or "no" to indicate if the user is in
-                     group wheel when they are trying to become root.  Some
-                     authentication types require the user to be in group
-                     wheel when using the su(1) program to become super user.
-  #+END_SRC
-
-  The auth module communicates with its caller through file descriptor 3.
-
-* Documentation
-
-  All of the high level authentication functions are described in
-  [[https://man.openbsd.org/authenticate][=authenticate(3)=]], with the lower level functions being described in
-  [[https://man.openbsd.org/auth_subr][=auth_subr(3)=]].
-
-* auth_userokay
-
-  The highest level function, and easiest to use is =auth_userokay=. It
-  takes four character arrays as arguments, =name=, =style=, =type=, and
-  =password=. It returns either a =0= for failure, of a non-zero value
-  for success.
-
-  This function lives inside =/lib/libc/gen/authenticate.c=
-
-  #+BEGIN_SRC c
-  int auth_userokay(char *name, char *style, char *type, char *password);
-  #+END_SRC
-
-  - =name= is the name of the user to be authenticated
-  - =style= is the login method to be used
-    - If =style= is =NULL=, the user's default login style will be
-      used. By default this is =passwd= on normal accounts.
-    - The style can be one of the installed authentication methods, like
-      =passwd=, =radius=, =skey=, =yubikey=, etc.
-    - There's more information about available styles in =login.conf(5)=
-    - Styles can also be installed through BSD Auth module packages
-  - =type= is the authentication type
-    - Types are defined in =login.conf= and define a group of allowed
-      auth styles
-    - If =type= is =NULL=, use the auth type for the user's login
-      class. The default type is =auth-default=, which allows
-      =psaswd= and =skey= auth methods.
-    - There's more information about how to add methods in =login.conf(5)=
-  - =password= is the password to test
-    - If =password= is =NULL=, then the user is interactively
-      prompted. This is required for auth styles using
-      challenge-response methods.
-    - If =password= is specified, then it's non-interactively tested
-
-  =auth_userokay= is just a wrapper around =auth_usercheck=, which
-  returns a finished auth session of type =auth_session_t=. It closes
-  the auth session using =auth_close= and returns the value returned
-  from closing.
-
-* auth_session_t
-
-  #+BEGIN_SRC c
-  struct auth_session_t {
-      char    *name;                 /* name of use being authenticated */
-      char    *style;                /* style of authentication used */
-      char    *class;                /* class of user */
-      char    *service;              /* type of service being performed */
-      char    *challenge;            /* last challenge issued */
-      int     flags;                 /* see below */
-      struct  passwd *pwd;           /* password entry for user */
-      struct  timeval now;           /* time of authentication */
-
-      int     state;                 /* authenticated state */
-
-      struct  rmfiles *rmlist;       /* list of files to remove on failure */
-      struct  authopts *optlist;     /* list of options to scripts */
-      struct  authdata *data;        /* additional data to send to scripts */
-
-      char    spool[MAXSPOOLSIZE];   /* data returned from login script */
-      int     index;                 /* how much returned thus far */
-
-      int     fd;                    /* connection to authenticator */
-
-      va_list ap0;                   /* argument list to auth_call */
-      va_list ap;                    /* additional arguments to auth_call */
-  };
-  #+END_SRC
-
-  Where =authdata=, =authopts=, and =rmfiles= are defined as
-
-  #+BEGIN_SRC c
-  struct rmfiles {
-      struct rmfiles  *next;
-      char            *file;
-  };
-
-  struct authopts {
-      struct authopts *next;
-      char            *opt;
-  };
-
-  struct authdata {
-      struct  authdata *next;
-      void    *ptr;
-      size_t   len;
-  };
-  #+END_SRC
-
-** auth_setdata
-
-** auth_setitem
-
-** auth_setoption
-
-** auth_setstate
-* auth_open
-
-  The =auth_open= function is used by several functions to create a
-  new auth session. It allocates an =auth_session_t= struct on the
-  heap, sets its default =service= to =login=, and it's =fd= to =-1=,
-  and returns the pointer.
-
-* auth_usercheck
-
-  #+BEGIN_SRC c
-  auth_session_t *auth_usercheck(char *name, char *style, char *type, char *password)
-  #+END_SRC
-
-  =auth_usercheck= checks the user name against the passwd db. It also
-  checks the login class against the =login.conf= db, along with
-  confirming the login styles available.
-
-  If the password is non-=NULL=, then it creates a new session using
-  =auth_open=. With the new session, =auth_usercheck= calls (with =as=
-  as the session struct)
-
-  #+BEGIN_SRC c
-  auth_setitem(as, AUTHV_SERVICE, "response");
-  auth_setdata(as, "", 1);
-  auth_setdata(as, password, strlen(password) + 1);
-  #+END_SRC
-
-  setting the service protocol to =response=, adding an empty line to
-  the session data, then adding the password as data. If the password is
-  =NULL=, it sets the =auth_session_t= pointer to =NULL=. It then passes
-  the user name, style, login class, and =NULL= char pointer to
-  =auth_verify=. The last two variables are received as variable
-  arguments. It then returns the auth session pointer the call
-  returns.
-
-* auth_verify
-
-  #+BEGIN_SRC c
-  auth_session_t *auth_verify(auth_session_t *as, char *style, char *name, ...)
-  #+END_SRC
-
-  =auth_verify= creates an auth session using =auth_open= if =as= is
-  =NULL=. It then sets the user name and style of the session, if the
-  respective arguments are non-=NULL=. It then copies its variable
-  arguments to the auth session's =va_list ap=, which is used inside
-  of =auth_call=.
-
-  After that it constructs the path of the authentication module by
-  combining =_PATH_AUTHPROG=, which is defined in =login_cap.h= as
-  =/usr/libexec/auth/login_=, and the authentication style. For the
-  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. 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",
-      auth_getitem(as, AUTHV_SERVICE), "--", name, (char *)NULL);
-  #+END_SRC
-
-* auth_call
-
-  #+BEGIN_SRC c
-  int auth_call(auth_session_t *as, char *path, ...)
-  #+END_SRC
-
-  <<here>>
-
-  ---
-  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[] = {
-      "PATH=" _PATH_DEFPATH,
-      "SHELL=" _PATH_BSHELL,
-      NULL,
-  };
-  #+END_SRC
-
-  Where both constants are defined in =paths.h= as
-
-  #+BEGIN_SRC c
-  #define	_PATH_DEFPATH	"/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin"
-  #define	_PATH_BSHELL	"/bin/sh"
-  #+END_SRC
-
-
-  The =exec='d process then listens on FD 3, which is one half of the
-  =sockpair= that was created earlier.
-
-  In the non-exec'd process, first the contents of the auth session's
-  =*data= are read in one at a time.
-
-  The data received through the back channel is then put into the
-  =spool= of the auth session using =_auth_spool(as, pfd[0])=. After
-  that the spooled data is scanned for key words defined in
-  =login_cap.h=.
-
-  #+BEGIN_SRC c
-  #define BI_AUTH         "authorize"         /* Accepted authentication */
-  #define BI_REJECT       "reject"            /* Rejected authentication */
-  #define BI_CHALLENGE    "reject challenge"  /* Reject with a challenge */
-  #define BI_SILENT       "reject silent"     /* Reject silently */
-  #define BI_REMOVE       "remove"            /* remove file on error */
-  #define BI_ROOTOKAY     "authorize root"    /* root authenticated */
-  #define BI_SECURE       "authorize secure"  /* okay on non-secure line */
-  #define BI_SETENV       "setenv"            /* set environment variable */
-  #define BI_UNSETENV     "unsetenv"          /* unset environment variable */
-  #define BI_VALUE        "value"             /* set local variable */
-  #define BI_EXPIRED      "reject expired"    /* account expired */
-  #define BI_PWEXPIRED    "reject pwexpired"  /* password expired */
-  #define BI_FDPASS       "fd"                /* child is passing an fd */
-  #+END_SRC
-
-  The [[https://man.openbsd.org/login.conf][=login.conf(5)=]] man page once again goes into greater detail on
-  these values.
-
-  #+BEGIN_SRC
-  authorize  The user has been authorized.
-
-  authorize secure
-             The user has been authorized and root should be allowed to
-             login even if this is not a secure terminal.  This should only
-             be sent by authentication styles that are secure over insecure
-             lines.
-
-  reject     Authorization is rejected.  This overrides any indication that
-             the user was authorized (though one would question the wisdom
-             in sending both a reject and an authorize command).
-
-  reject challenge
-             Authorization was rejected and a challenge has been made
-             available via the value challenge.
-
-  reject silent
-             Authorization is rejected, but no error messages should be
-             generated.
-
-  remove file
-             If the login session fails for any reason, remove file before
-             termination.
-
-  setenv name value
-             If the login session succeeds, the environment variable name
-             should be set to the specified value.
-
-  unsetenv name
-             If the login session succeeds, the environment variable name
-             should be removed.
-
-  value name value
-             Set the internal variable name to the specified value.  The
-             value should only contain printable characters.  Several \
-             sequences may be used to introduce non printing characters.
-             These are:
-
-             \n      A newline.
-
-             \r      A carriage return.
-
-             \t      A tab.
-
-             \xxx    The character represented by the octal value xxx.  The
-                     value may be one, two, or three octal digits.
-
-             \c      The string is replaced by the value of c.  This allows
-                     quoting an initial space or the \ character itself.
-
-
-             The following values are currently defined:
-
-             challenge
-                     See section on challenges below.
-
-             errormsg
-                     If set, the value is the reason authentication failed.
-                     The calling program may choose to display this when
-                     rejecting the user, but display is not required.
-
-  #+END_SRC
-
-
-  It is looking for lines that start with either =BI_AUTH=
-  (=authorize=), or =BI_REJECT= (=reject=). If the line is still longer,
-  it continues to scan for any other qualifiers such as =pwexpired= or
-  =silent=. The struct's =state= is set to one using the =AUTH_= values
-  from =login_cap.h= accordingly.
-
-  #+BEGIN_SRC c
-  /*
-   * bits which can be returned by authenticate()/auth_scan()
-   */
-  #define  AUTH_OKAY       0x01            /* user authenticated */
-  #define  AUTH_ROOTOKAY   0x02            /* authenticated as root */
-  #define  AUTH_SECURE     0x04            /* secure login */
-  #define  AUTH_SILENT     0x08            /* silent rejection */
-  #define  AUTH_CHALLENGE  0x10            /* a challenge was given */
-  #define  AUTH_EXPIRED    0x20            /* account expired */
-  #define  AUTH_PWEXPIRED  0x40            /* password expired */
-  #+END_SRC
-
-** _auth_spool
-
-** _recv_fd
-
-* auth_close
-  =auth_close= is the function responsible for cleaning up the session
-  and taking care of the values returned though the back channel.
-
-  It first sets the environment variables returned through the back
-  channel by passing the auth session to =auth_setenv=. It then goes
-  through the =rmlist= of the session, deleting the files if the
-  session reported a failure. It then zeroes out all sensitive
-  information, and frees the various structs associated with the current
-  =auth_session_t=, and then the session itself. Finally it returns
-  the session's state =&='ed with =AUTH_ALLOW=.
-* grapgh?
-# Setting env on auth_close(as)
-# partual rewrite below
-
-The call graph for =auth_userokay= looks something like this:
-
-#+BEGIN_SRC c
-int auth_userokay(char *name, char *style, char *type, char *password)
-#+END_SRC
-
-calls ~auth_usercheck~ and then calls ~auth_close~ on the returned
-~auth_session_t~. The value returned from ~auth_close~ is then
-returned.
-
-#+BEGIN_SRC c
-auth_session_t *auth_usercheck(char *name, char *style, char *type, char *password)
-#+END_SRC
-
-Validates the checks that the user exists, gets the user's login
-class, verifies the auth type, and that the auth style can be used.
-
-It creates an auth session struct.
-
-If the password is provided it sets the service type to =response=,
-and adds the adds the password to the auth data. Otherwise it
-leaves it empty.
diff --git a/content/posts/how-this-blog-works.org b/content/posts/how-this-blog-works.org
deleted file mode 100644
index 80fa1ca..0000000
--- a/content/posts/how-this-blog-works.org
+++ /dev/null
@@ -1,239 +0,0 @@
-#+TITLE: Creating Self-Hosted Hugo Blog on OpenBSD
-#+DATE: 2020-06-17T21:03:26-04:00
-#+DRAFT: true
-#+DESCRIPTION:
-#+TAGS[]: hugo openbsd
-#+KEYWORDS[]:
-#+SLUG:
-#+SUMMARY:
-#+SHOWTOC: true
-
-When creating this blog, there were a couple of factors I kept in mind
-while trying to figure out how I was going to set it up:
-
-- Simple
-- Version controlled
-- Easy to host on OpenBSD
-- Minimal maintenance
-- Good integration with Emacs
-# more
-That's how I came up with what I currently use. Let's walk through how
-it works.
-
-* Framework
-
-  The blog engine is [[https://gohugo.io/][hugo]], a static site generator. I chose this over
-  something dynamic like wordpress for several reasons.
-
-  First of all, it's very easy to manage, blog posts are just simple
-  files written in one of the markup languages hugo supports. Being
-  statically generated is also a massive advantage in terms of
-  maintenance. With something like wordpress, you have to be careful to
-  keep your site and plugins up to date.
-
-  Since there's no dynamic content generation or database involved with
-  hugo, the attack surface is dramatically decreased. No possibility for
-  SQL injection, PHP RATs, accidental shell access, or hacked
-  credentials. The entire site is generated using a single command after
-  a new post is created, and then moved to the web server's root
-  directory.
-
-  Being all flat files also means the entire thing can very easily be
-  tracked using =git= (or maybe [[https://gameoftrees.org/][got]], eventually), in fact that's the
-  recommended way to use hugo. There's no fear I'll accidentally delete
-  something, as I can always go back to a previous commit and restore
-  it.
-
-  Since hugo is written in go, it's trivial to compile on OpenBSD, and
-  is actually available directly from the OpenBSD package manager right
-  out of the gate.
-
-  Maybe the most important thing to be however, is that hugo natively
-  supports org-mode markup. I write all my notes, both personal and work
-  related, in org-mode. It makes converting my notes into blog posts
-  really easy. It also lets me leverage my existing Emacs setup, which
-  comes in handy often. While it's not very well documented, since
-  org-mode markup is a bit of a second class citizen in the hugo world,
-  it's pretty easy to figure out.
-
-* Prerequisites
-
-  This can be hosted on a very cheap VPS since it only has to serve
-  static pages. For OpenBSD hosting I would recommend either [[https://www.vultr.com/][Vultr]] or
-  [[https://openbsd.amsterdam/][OpenBSD Amsterdam]].
-
-** Server
-  The only thing that's required on the host server is =git=, although
-  you could even get away without that if you chose to host your git
-  repository elsewhere, like on github.
-
-  #+BEGIN_SRC shell
-  pkg_add git
-  #+END_SRC
-
-** Local machine
-  On the local machine you'll need both =git= and =rsync=. Both might
-  already be installed depending on the system you're on. If not,
-  check your package manager for details on how to install them. In
-  the case of Ubuntu or Debian it would be
-
-  #+BEGIN_SRC shell
-  sudo apt install git rsync
-  #+END_SRC
-
-  or for Fedora
-
-  #+BEGIN_SRC shell
-  sudo dnf install git rsync
-  #+END_SRC
-
-* Version Control
-
-  I wanted to try to keep things as simple as possible for this. The
-  "origin" for the blog is simply a bare git repository in the =blog=
-  user's home directory.
-
-** Setting up the blog user
-
-   First I set up the blog user
-   #+BEGIN_SRC shell
-   useradd -m blog
-   #+END_SRC
-
-   I then placed my public SSH key in its =authorized_keys= file
-
-   #+BEGIN_SRC shell
-   mkdir -m 700 /home/blog/.ssh
-   cp /root/.ssh/authorized_keys /home/blog/.ssh/
-   chown -R blog:blog /home/blog
-   #+END_SRC
-
-   I then logged in as the blog user and initialize the bare git
-   repository.
-
-   #+BEGIN_SRC shell
-   su blog
-   cd   # cd with no arguments goes to home directory
-   git init --bare blog.git
-   #+END_SRC
-
-** Cloning the repository
-
-   Cloning the repository onto my local machine is very easy at this
-   point. As long as my private keys are in the =blog= user's
-   =authorized_keys=, git will take care of the rest.
-
-   #+BEGIN_SRC shell
-   # on my local machine
-   git clone blog@lambda.cx:blog.git
-   #+END_SRC
-
-   I can now work on the blog as I would any other git repository,
-   pulling with =git pull= and pushing with =git push=.
-
-* Web Server
-
-  Since this blog is going to be hosted on OpenBSD, we don't need to
-  install a web server, as it already comes with one built in.
-
-  Setting up =httpd= couldn't be easier, the configuration syntax is
-  very straight forward. If you would like to see a full breakdown of
-  the options available, check out the man page with =man
-  httpd.conf=. The example configuration in =/etc/examples/httpd.conf=
-  is also a good starting point.
-
-  In this case the simplest configuration would be as follows
-
-  # js chosen for prism.js syntax highlighting
-  #+BEGIN_SRC js
-  server "blog.lambda.cx" {
-      listen on * port 80
-      root "/htdocs/blog.lambda.cx"
-  }
-  #+END_SRC
-
-  Despite how it looks, the =htdocs= folder doesn't reside in the
-  system root (=/=) directory. It actually lives in =/var/www/htdocs=,
-  and only appears that way because =httpd= gets automatically
-  =chroot='ed in =/var/www/= for security reasons.
-
-  Finally we start and enable =httpd= using =rcctl=
-
-  #+BEGIN_SRC shell
-  rcctl enable httpd
-  rcctl start httpd
-  #+END_SRC
-
-
-  For more information about how to set up SSL with Let's Encrypt,
-  check out [[{{< ref "posts/letsencrypt-on-openbsd" >}}][this post]].
-
-* Using Hugo
-
-  There's not much to say here. Hugo's [[https://gohugo.io/][website]] has good documentation
-  on how to get started creating a blog. I'll be covering the
-  intricacies of using org-mode with hugo in the future.
-
-* Deployment
-
-  The system used to deploy this blog is incredibly simple, involving
-  only =rsync=, =hugo=, and a small shell script.
-
-** Server
-  First you have to allow the =blog= user to write to the website
-  root. We'll do this by making it the owner of
-  =/var/www/htdocs/blog.lambda.cx=.
-
-  #+BEGIN_SRC shell
-  chown -R blog /var/www/htdocs/blog.lambda.cx
-  #+END_SRC
-
-** Local machine
-
-   This is the script used to deploy the website. It's placed in the
-   root of the hugo git repository.
-
-   #+BEGIN_SRC shell
-   #!/bin/sh
-   set -e
-
-   cd '$(dirname "$0")'
-   hugo
-   rsync -va --progress --delete --rsync-path="/usr/bin/openrsync" public/ blog@lambda.cx:/var/www/htdocs/lambda.cx/blog
-   #+END_SRC
-
-   Going through it line by line:
-
-   - ~set -e~ Tells the shell to exit if any commands fail instead of
-     continuing execution. If ~hugo~ has a problem and exits with an
-     error, don't sync with the server.
-   - ~cd '$(dirname "$0")'~ Changes to the script's directory. This is
-     used in case you're running it from somewhere else.
-   - ~hugo~ Compile the website into static files located in the
-     =public= directory.
-   - ~rsync -va --progress --rsync-path="/usr/bin/openrsync" public/
-     blog@lambda.cx:/var/www/htdocs/lambda.cx/blog~ This one is bigger
-     so I'll break it down.
-     - =rsync= A command that synchronizes files between two directories
-     - =-v= Be verbose, this is optional but I like it
-     - =-a= Stands for "archive": copy recursively, keep
-       permissions, etc. See the =rsync= man page if you're curious.
-     - =--progress= Show progress, also optional
-     - =--delete= Removed files on the server that no longer exist on
-       the client
-     - ~--rsync-path="/usr/bin/openrsync"~ This line is very important
-       for OpenBSD servers. OpenBSD has its own =rsync= implementation
-       called =openrsync=. Without this argument, =rsync= will connect
-       to the server, see that the =rsync= command doesn't exist, and
-       fail.
-     - =public/= Specify which folder we want to sync. The trailing
-       =/= is important. Without it =rsync= will copy the folder
-       instead of the folder's contents, which is what we want.
-     - =blog@lambda.cx:/var/www/htdocs/lambda.cx/blog= Login to user
-       =blog= on server =lambda.cx=, syncing files with the
-       =/var/www/htdocs/lambda.cx/blog= directory.
-
-   The reason to use =rsync= here instead of something like =scp= is
-   that =rsync= won't upload files it doesn't need to, so if 3/4 of
-   the files didn't change when you updated the blog, it won't waste
-   time re-uploading them.
diff --git a/content/posts/openbsd-dhcp-server/index.org b/content/posts/openbsd-dhcp-server/index.org
deleted file mode 100644
index 0578f87..0000000
--- a/content/posts/openbsd-dhcp-server/index.org
+++ /dev/null
@@ -1,8 +0,0 @@
-#+TITLE: How to Setup a DHCP server on OpenBSD
-#+DATE: 2020-07-07T19:22:38-04:00
-#+DRAFT: true
-#+DESCRIPTION:
-#+TAGS[]: openbsd dhcp
-#+KEYWORDS[]: openbsd dhcp
-#+SLUG:
-#+SUMMARY:
-- 
cgit v1.2.3