From 894afa96cd14a84cd1a1bcfb9523f10210aebb7c Mon Sep 17 00:00:00 2001
From: Dante Catalfamo
Date: Mon, 18 Oct 2021 17:36:47 -0400
Subject: bsd-auth: no longer WIP
---
.../WIP-how-bsd-authentication-works/gen_dot.rb | 99 -
.../WIP-how-bsd-authentication-works/graph.dot | 152 --
.../WIP-how-bsd-authentication-works/graph.svg | 856 ------
.../WIP-how-bsd-authentication-works/index.org | 2811 --------------------
.../WIP-how-bsd-authentication-works/notes.org | 83 -
.../openbsd_internals.gif | Bin 690203 -> 0 bytes
.../posts/how-bsd-authentication-works/gen_dot.rb | 99 +
.../posts/how-bsd-authentication-works/graph.dot | 152 ++
.../posts/how-bsd-authentication-works/graph.svg | 856 ++++++
.../posts/how-bsd-authentication-works/index.org | 2811 ++++++++++++++++++++
.../posts/how-bsd-authentication-works/notes.org | 83 +
.../openbsd_internals.gif | Bin 0 -> 690203 bytes
12 files changed, 4001 insertions(+), 4001 deletions(-)
delete mode 100755 content/posts/WIP-how-bsd-authentication-works/gen_dot.rb
delete mode 100644 content/posts/WIP-how-bsd-authentication-works/graph.dot
delete mode 100644 content/posts/WIP-how-bsd-authentication-works/graph.svg
delete mode 100644 content/posts/WIP-how-bsd-authentication-works/index.org
delete mode 100644 content/posts/WIP-how-bsd-authentication-works/notes.org
delete mode 100644 content/posts/WIP-how-bsd-authentication-works/openbsd_internals.gif
create mode 100755 content/posts/how-bsd-authentication-works/gen_dot.rb
create mode 100644 content/posts/how-bsd-authentication-works/graph.dot
create mode 100644 content/posts/how-bsd-authentication-works/graph.svg
create mode 100644 content/posts/how-bsd-authentication-works/index.org
create mode 100644 content/posts/how-bsd-authentication-works/notes.org
create mode 100644 content/posts/how-bsd-authentication-works/openbsd_internals.gif
diff --git a/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb b/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb
deleted file mode 100755
index 9f71876..0000000
--- a/content/posts/WIP-how-bsd-authentication-works/gen_dot.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-# Copyright (C) 2021 Dante Catalfamo
-# SPDX-License-Identifier: MIT
-
-require 'digest'
-require 'set'
-
-SOURCE_DIR = File.join Dir.home, 'src', 'github.com', 'openbsd', 'src', 'lib', 'libc', 'gen'
-FILENAMES = %w[authenticate.c auth_subr.c login_cap.c].freeze
-
-FUNCTION_REGEX = /^\w.*?$\n(?!DEF)(\w*)\(.*?\)\n\{(.*?)^\}/m.freeze
-ONELINE_FUNCTION_REFGEX = /^\w.*?(\w*)\(.*?\).*?\{(.*?)\}/.freeze
-CALL_REGEX = /[^\n](\w+)\(.*?\)/.freeze
-
-class FunctionDigraph
- attr_accessor :pairs, :subgraphs
-
- class Subgraph
- attr_accessor :name, :label, :functions
-
- def initialize(name, label)
- @name = name
- @label = label
- @functions = []
- end
-
- def emit
- puts "subgraph cluster_#{name} {"
- puts "label = \"#{label}\""
- functions.each { |f| puts f unless f == 'DEF_WEAK' }
- puts '}'
- end
- end
-
- class Pair
- attr_accessor :to, :from
-
- def initialize(from, to)
- @from = from
- @to = to
- end
-
- def emit
- puts "#{from} -> #{to} [color = \"##{color}\"]"
- end
-
- def color
- Digest::MD5.hexdigest(from)[..5]
- end
- end
-
- def initialize
- @pairs = []
- @subgraphs = []
- end
-
- def emit
- puts 'digraph G {'
- puts 'rankdir=LR'
- puts 'splines=ortho'
- puts 'graph [pad="0.5", nodesep="0.5", ranksep="1.5"]'
- all_functions = Set.new
- @subgraphs.each { |s| all_functions.merge(s.functions) }
- @subgraphs.each(&:emit)
- @pairs.uniq { |p| [p.to, p.from] }.each do |p|
- p.emit if all_functions.include?(p.to)
- end
- puts '}'
- end
-
- def parse_files(filenames)
- filenames.each do |filename|
- contents = File.read(filename)
- basename = File.basename filename
- subgraph = Subgraph.new(basename.gsub(/\..*/, ''), basename)
- functions = contents.scan(FUNCTION_REGEX)
- oneliners = contents.scan(ONELINE_FUNCTION_REFGEX)
- functions.concat(oneliners) unless oneliners.empty?
- functions.each do |function|
- function_name = function[0]
- function_body = function[1]
- subgraph.functions << function_name
- function_body.scan(CALL_REGEX) do |call|
- @pairs << Pair.new(function_name, call[0])
- end
- end
- @subgraphs << subgraph
- end
- end
-end
-
-fg = FunctionDigraph.new
-
-files = FILENAMES.map { |f| File.join(SOURCE_DIR, f) }
-fg.parse_files files
-
-fg.emit
diff --git a/content/posts/WIP-how-bsd-authentication-works/graph.dot b/content/posts/WIP-how-bsd-authentication-works/graph.dot
deleted file mode 100644
index 9a2be3c..0000000
--- a/content/posts/WIP-how-bsd-authentication-works/graph.dot
+++ /dev/null
@@ -1,152 +0,0 @@
-digraph G {
-rankdir=LR
-splines=ortho
-graph [pad="0.5", nodesep="0.5", ranksep="1.5"]
-subgraph cluster_authenticate {
-label = "authenticate.c"
-auth_mkvalue
-auth_checknologin
-_auth_checknologin
-auth_cat
-_auth_validuser
-auth_approval
-auth_usercheck
-auth_userokay
-auth_userchallenge
-auth_userresponse
-auth_verify
-}
-subgraph cluster_auth_subr {
-label = "auth_subr.c"
-auth_open
-auth_clean
-auth_close
-auth_challenge
-auth_setenv
-auth_clrenv
-auth_getitem
-auth_setitem
-auth_setoption
-auth_clroptions
-auth_clroption
-auth_setdata
-auth_setpwd
-auth_getvalue
-auth_check_expire
-auth_check_change
-auth_call
-_recv_fd
-_auth_spool
-_add_rmlist
-_auth_next_arg
-auth_setstate
-auth_set_va_list
-auth_getstate
-auth_getpwd
-}
-subgraph cluster_login_cap {
-label = "login_cap.c"
-login_getclass
-login_getstyle
-login_getcapstr
-login_getcaptime
-login_getcapnum
-login_getcapsize
-login_getcapbool
-login_close
-gsetrl
-setclasscontext
-setusercontext
-setuserpath
-setuserenv
-login_setenv
-strtosize
-strtolimit
-multiply
-secure_path
-expandstr
-}
-auth_checknologin -> _auth_checknologin [color = "#f0bfd8"]
-_auth_checknologin -> login_getcapbool [color = "#f51748"]
-_auth_checknologin -> login_getcapstr [color = "#f51748"]
-_auth_checknologin -> auth_cat [color = "#f51748"]
-auth_approval -> auth_getitem [color = "#8f94eb"]
-auth_approval -> auth_getpwd [color = "#8f94eb"]
-auth_approval -> _auth_validuser [color = "#8f94eb"]
-auth_approval -> login_getclass [color = "#8f94eb"]
-auth_approval -> login_close [color = "#8f94eb"]
-auth_approval -> login_getcapstr [color = "#8f94eb"]
-auth_approval -> auth_open [color = "#8f94eb"]
-auth_approval -> auth_setstate [color = "#8f94eb"]
-auth_approval -> auth_setitem [color = "#8f94eb"]
-auth_approval -> auth_check_expire [color = "#8f94eb"]
-auth_approval -> login_getcapbool [color = "#8f94eb"]
-auth_approval -> auth_call [color = "#8f94eb"]
-auth_approval -> auth_close [color = "#8f94eb"]
-auth_approval -> auth_getstate [color = "#8f94eb"]
-auth_usercheck -> _auth_validuser [color = "#96fc6d"]
-auth_usercheck -> login_getclass [color = "#96fc6d"]
-auth_usercheck -> login_getstyle [color = "#96fc6d"]
-auth_usercheck -> login_close [color = "#96fc6d"]
-auth_usercheck -> auth_open [color = "#96fc6d"]
-auth_usercheck -> auth_setitem [color = "#96fc6d"]
-auth_usercheck -> auth_setdata [color = "#96fc6d"]
-auth_usercheck -> auth_verify [color = "#96fc6d"]
-auth_userokay -> auth_usercheck [color = "#3eb09b"]
-auth_userokay -> auth_close [color = "#3eb09b"]
-auth_userchallenge -> _auth_validuser [color = "#0db8d4"]
-auth_userchallenge -> login_getclass [color = "#0db8d4"]
-auth_userchallenge -> login_getstyle [color = "#0db8d4"]
-auth_userchallenge -> auth_open [color = "#0db8d4"]
-auth_userchallenge -> login_close [color = "#0db8d4"]
-auth_userchallenge -> auth_setitem [color = "#0db8d4"]
-auth_userchallenge -> auth_close [color = "#0db8d4"]
-auth_userchallenge -> auth_challenge [color = "#0db8d4"]
-auth_userresponse -> auth_setstate [color = "#cc7ac2"]
-auth_userresponse -> auth_getitem [color = "#cc7ac2"]
-auth_userresponse -> _auth_validuser [color = "#cc7ac2"]
-auth_userresponse -> auth_close [color = "#cc7ac2"]
-auth_userresponse -> auth_setdata [color = "#cc7ac2"]
-auth_userresponse -> auth_getstate [color = "#cc7ac2"]
-auth_userresponse -> auth_check_expire [color = "#cc7ac2"]
-auth_verify -> auth_open [color = "#83192f"]
-auth_verify -> auth_setstate [color = "#83192f"]
-auth_verify -> auth_setitem [color = "#83192f"]
-auth_verify -> auth_getitem [color = "#83192f"]
-auth_verify -> _auth_validuser [color = "#83192f"]
-auth_verify -> auth_set_va_list [color = "#83192f"]
-auth_verify -> auth_call [color = "#83192f"]
-auth_clean -> auth_clrenv [color = "#759227"]
-auth_clean -> auth_setitem [color = "#759227"]
-auth_close -> auth_setenv [color = "#4a5505"]
-auth_challenge -> _auth_validuser [color = "#5e3ac3"]
-auth_challenge -> auth_getvalue [color = "#5e3ac3"]
-auth_setitem -> auth_setitem [color = "#e67693"]
-auth_setitem -> _auth_validuser [color = "#e67693"]
-auth_check_expire -> auth_setpwd [color = "#739550"]
-auth_check_change -> auth_setpwd [color = "#902d9d"]
-auth_call -> _auth_next_arg [color = "#a9e6c9"]
-auth_call -> _auth_spool [color = "#a9e6c9"]
-auth_call -> _add_rmlist [color = "#a9e6c9"]
-auth_call -> auth_clrenv [color = "#a9e6c9"]
-_auth_spool -> _recv_fd [color = "#977e1c"]
-login_getstyle -> login_getcapstr [color = "#51a344"]
-login_getcapsize -> strtolimit [color = "#97959e"]
-gsetrl -> login_getcaptime [color = "#35d53a"]
-gsetrl -> login_getcapsize [color = "#35d53a"]
-gsetrl -> login_getcapnum [color = "#35d53a"]
-setclasscontext -> login_getclass [color = "#5b8e44"]
-setclasscontext -> setusercontext [color = "#5b8e44"]
-setclasscontext -> login_close [color = "#5b8e44"]
-setusercontext -> login_getclass [color = "#7eb75f"]
-setusercontext -> login_close [color = "#7eb75f"]
-setusercontext -> login_getcapnum [color = "#7eb75f"]
-setusercontext -> setuserenv [color = "#7eb75f"]
-setusercontext -> setuserpath [color = "#7eb75f"]
-setuserpath -> login_setenv [color = "#35ed7d"]
-setuserenv -> login_setenv [color = "#a1aa6a"]
-login_setenv -> expandstr [color = "#502c54"]
-strtosize -> multiply [color = "#a61402"]
-strtosize -> strtosize [color = "#a61402"]
-strtolimit -> strtosize [color = "#c987ba"]
-}
diff --git a/content/posts/WIP-how-bsd-authentication-works/graph.svg b/content/posts/WIP-how-bsd-authentication-works/graph.svg
deleted file mode 100644
index 94f22d2..0000000
--- a/content/posts/WIP-how-bsd-authentication-works/graph.svg
+++ /dev/null
@@ -1,856 +0,0 @@
-
-
-
-
-
diff --git a/content/posts/WIP-how-bsd-authentication-works/index.org b/content/posts/WIP-how-bsd-authentication-works/index.org
deleted file mode 100644
index f0623c2..0000000
--- a/content/posts/WIP-how-bsd-authentication-works/index.org
+++ /dev/null
@@ -1,2811 +0,0 @@
-#+TITLE: How BSD Authentication Works
-#+DATE: 2021-10-18T17:27:13-04:00
-#+DRAFT: true
-#+SHOWTOC: true
-#+DESCRIPTION: A walkthrough of how OpenBSD's BSD Auth framework functions
-#+TAGS[]: openbsd security
-#+KEYWORDS[]: openbsd security
-#+SLUG:
-#+SUMMARY:
-
-#+ATTR_HTML: :title OpenBSD Internals
-#+ATTR_HTML: :alt OpenBSD mascot cutaway view with spinning gears inside
-[[file:openbsd_internals.gif]]
-
-* History
- :PROPERTIES:
- :CUSTOM_ID: history
- :END:
-
- The way OpenBSD authenticates users is quite different from other
- Unix-like operating systems. Most other systems like AIX, Solaris,
- Linux, the other BSDs, and MacOS, use a framework called [[https://en.wikipedia.org/wiki/Pluggable_authentication_module][Pluggable
- Authentication Module]] (PAM). The two main implementations are [[http://www.linux-pam.org/][Linux
- PAM]] and [[https://www.openpam.org/][OpenPAM]]. PAM modules are created as dynamically loaded
- shared objects, which communicate using a combination of common and
- implementation specific 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]]). It's
- 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]] file. While it can
- be flexible, it's highly complex and very easy to mis-configure,
- leaving you open to strange and hard to track down authentication
- bugs. On top of that, the fact that it's a shared library means that
- any vulnerability in a poorly vetted authentication module gives
- attackers direct access to the internals of your application. Author
- Michael W. Lucas said it best when he described PAM as
- [[https://www.youtube.com/watch?v=-CXp3byvI1g][unstandardized black magic]].
-
- OpenBSD on the other hand uses a mechanism called BSD
- Authentication. It was originally developed for a now-defunct
- 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 then 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. The module 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)=]].
-
-* Documentation
- :PROPERTIES:
- :CUSTOM_ID: documentation
- :END:
-
- 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)=]].
-
- Click on any function prototype in this post to see its definition.
-
- I've also created a [[#graph][graph]] at the bottom of the post to help
- visualize the function calls.
-
- All code snippets from this blog post belong to the OpenBSD
- contributors. Please see the [[#copyright][Copyright]] section for details.
-
-* BSD Auth Modules
- :PROPERTIES:
- :CUSTOM_ID: modules
- :END:
-
- Modules are located in =/usr/libexec/auth/= with the naming
- convention =login_
-#+end_export
diff --git a/content/posts/WIP-how-bsd-authentication-works/notes.org b/content/posts/WIP-how-bsd-authentication-works/notes.org
deleted file mode 100644
index 9bd67d4..0000000
--- a/content/posts/WIP-how-bsd-authentication-works/notes.org
+++ /dev/null
@@ -1,83 +0,0 @@
-* Notes
- https://web.archive.org/web/20170327150148/http://www.penzin.net/bsdauth/
- - In the man page for [[https://man.openbsd.org/auth_subr.3#auth_call][=auth_call=]] it says
- #+begin_src text
- 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_src
-
- However I don't see this enforced anywhere, I even wrote a small test
- script to prove it.
-
- #+CAPTION: =authfail.c=
- #+begin_src c
- #include
- #include
- #include
- #include
-
- int main(void) {
- auth_session_t *as;
-
- as = auth_open();
- auth_call(as, "/home/dante/auth_tests/authtest/test", "hello", NULL);
- auth_close(as);
- }
- #+end_src
-
- Changing ="/home/dante/auth_tests/authtest/test"= to the location
- of the =test= binary.
-
- #+CAPTION: =test.c=
- #+begin_src c
- #include
-
- int main(void) {
- printf("Hello! I don't have a secure path!\n");
- return 0;
- }
- #+end_src
-
- #+CAPTION: =Makefile=
- #+begin_src makefile
- CFLAGS = -Wall -Wextra
-
- run: authfail test
- ./authfail
-
- authfail: authfail.c
- $(CC) -o $@ $(CFLAGS) $<
-
- test: test.c
- $(CC) -o $@ $(CFLAGS) $<
- #+end_src
-
- Which results in the following:
-
- #+begin_src text
- $ pwd && ls -l && make
- /home/dante/auth_tests/authtest
- total 12
- -rw-r--r-- 1 dante dante 143 May 30 19:20 Makefile
- -rw-r--r-- 1 dante dante 248 May 29 19:30 authfail.c
- -rw-r--r-- 1 dante dante 115 May 29 19:22 test.c
- cc -o authfail -Wall -Wextra authfail.c
- cc -o test -Wall -Wextra test.c
- ./authfail
- Hello! I don't have a secure path!
- #+end_src
-
- - The manpage also says the path is limited to =/bin/= and =/usr/bin=,
- which is also not the case.
-
- - The man page describes the interface for =auth_getitem= is in the
- format of =AUTH_- =, but in reality it is =AUTHV_
- =.
-
- # Ask jcs about the file descriptor situation, I don't understand it
- # after reading both the man page and source.
-
- - The [[#auth_getchallenge][=auth_getchallenge=]] function in the [[https://man.openbsd.org/auth_subr.3#auth_getchallenge][=auth_subr(3)=]] man page
- doesn't seem to exist in the source code.
-
-** TODO How are these configured in login.conf?
diff --git a/content/posts/WIP-how-bsd-authentication-works/openbsd_internals.gif b/content/posts/WIP-how-bsd-authentication-works/openbsd_internals.gif
deleted file mode 100644
index 5088082..0000000
Binary files a/content/posts/WIP-how-bsd-authentication-works/openbsd_internals.gif and /dev/null differ
diff --git a/content/posts/how-bsd-authentication-works/gen_dot.rb b/content/posts/how-bsd-authentication-works/gen_dot.rb
new file mode 100755
index 0000000..9f71876
--- /dev/null
+++ b/content/posts/how-bsd-authentication-works/gen_dot.rb
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+# Copyright (C) 2021 Dante Catalfamo
+# SPDX-License-Identifier: MIT
+
+require 'digest'
+require 'set'
+
+SOURCE_DIR = File.join Dir.home, 'src', 'github.com', 'openbsd', 'src', 'lib', 'libc', 'gen'
+FILENAMES = %w[authenticate.c auth_subr.c login_cap.c].freeze
+
+FUNCTION_REGEX = /^\w.*?$\n(?!DEF)(\w*)\(.*?\)\n\{(.*?)^\}/m.freeze
+ONELINE_FUNCTION_REFGEX = /^\w.*?(\w*)\(.*?\).*?\{(.*?)\}/.freeze
+CALL_REGEX = /[^\n](\w+)\(.*?\)/.freeze
+
+class FunctionDigraph
+ attr_accessor :pairs, :subgraphs
+
+ class Subgraph
+ attr_accessor :name, :label, :functions
+
+ def initialize(name, label)
+ @name = name
+ @label = label
+ @functions = []
+ end
+
+ def emit
+ puts "subgraph cluster_#{name} {"
+ puts "label = \"#{label}\""
+ functions.each { |f| puts f unless f == 'DEF_WEAK' }
+ puts '}'
+ end
+ end
+
+ class Pair
+ attr_accessor :to, :from
+
+ def initialize(from, to)
+ @from = from
+ @to = to
+ end
+
+ def emit
+ puts "#{from} -> #{to} [color = \"##{color}\"]"
+ end
+
+ def color
+ Digest::MD5.hexdigest(from)[..5]
+ end
+ end
+
+ def initialize
+ @pairs = []
+ @subgraphs = []
+ end
+
+ def emit
+ puts 'digraph G {'
+ puts 'rankdir=LR'
+ puts 'splines=ortho'
+ puts 'graph [pad="0.5", nodesep="0.5", ranksep="1.5"]'
+ all_functions = Set.new
+ @subgraphs.each { |s| all_functions.merge(s.functions) }
+ @subgraphs.each(&:emit)
+ @pairs.uniq { |p| [p.to, p.from] }.each do |p|
+ p.emit if all_functions.include?(p.to)
+ end
+ puts '}'
+ end
+
+ def parse_files(filenames)
+ filenames.each do |filename|
+ contents = File.read(filename)
+ basename = File.basename filename
+ subgraph = Subgraph.new(basename.gsub(/\..*/, ''), basename)
+ functions = contents.scan(FUNCTION_REGEX)
+ oneliners = contents.scan(ONELINE_FUNCTION_REFGEX)
+ functions.concat(oneliners) unless oneliners.empty?
+ functions.each do |function|
+ function_name = function[0]
+ function_body = function[1]
+ subgraph.functions << function_name
+ function_body.scan(CALL_REGEX) do |call|
+ @pairs << Pair.new(function_name, call[0])
+ end
+ end
+ @subgraphs << subgraph
+ end
+ end
+end
+
+fg = FunctionDigraph.new
+
+files = FILENAMES.map { |f| File.join(SOURCE_DIR, f) }
+fg.parse_files files
+
+fg.emit
diff --git a/content/posts/how-bsd-authentication-works/graph.dot b/content/posts/how-bsd-authentication-works/graph.dot
new file mode 100644
index 0000000..9a2be3c
--- /dev/null
+++ b/content/posts/how-bsd-authentication-works/graph.dot
@@ -0,0 +1,152 @@
+digraph G {
+rankdir=LR
+splines=ortho
+graph [pad="0.5", nodesep="0.5", ranksep="1.5"]
+subgraph cluster_authenticate {
+label = "authenticate.c"
+auth_mkvalue
+auth_checknologin
+_auth_checknologin
+auth_cat
+_auth_validuser
+auth_approval
+auth_usercheck
+auth_userokay
+auth_userchallenge
+auth_userresponse
+auth_verify
+}
+subgraph cluster_auth_subr {
+label = "auth_subr.c"
+auth_open
+auth_clean
+auth_close
+auth_challenge
+auth_setenv
+auth_clrenv
+auth_getitem
+auth_setitem
+auth_setoption
+auth_clroptions
+auth_clroption
+auth_setdata
+auth_setpwd
+auth_getvalue
+auth_check_expire
+auth_check_change
+auth_call
+_recv_fd
+_auth_spool
+_add_rmlist
+_auth_next_arg
+auth_setstate
+auth_set_va_list
+auth_getstate
+auth_getpwd
+}
+subgraph cluster_login_cap {
+label = "login_cap.c"
+login_getclass
+login_getstyle
+login_getcapstr
+login_getcaptime
+login_getcapnum
+login_getcapsize
+login_getcapbool
+login_close
+gsetrl
+setclasscontext
+setusercontext
+setuserpath
+setuserenv
+login_setenv
+strtosize
+strtolimit
+multiply
+secure_path
+expandstr
+}
+auth_checknologin -> _auth_checknologin [color = "#f0bfd8"]
+_auth_checknologin -> login_getcapbool [color = "#f51748"]
+_auth_checknologin -> login_getcapstr [color = "#f51748"]
+_auth_checknologin -> auth_cat [color = "#f51748"]
+auth_approval -> auth_getitem [color = "#8f94eb"]
+auth_approval -> auth_getpwd [color = "#8f94eb"]
+auth_approval -> _auth_validuser [color = "#8f94eb"]
+auth_approval -> login_getclass [color = "#8f94eb"]
+auth_approval -> login_close [color = "#8f94eb"]
+auth_approval -> login_getcapstr [color = "#8f94eb"]
+auth_approval -> auth_open [color = "#8f94eb"]
+auth_approval -> auth_setstate [color = "#8f94eb"]
+auth_approval -> auth_setitem [color = "#8f94eb"]
+auth_approval -> auth_check_expire [color = "#8f94eb"]
+auth_approval -> login_getcapbool [color = "#8f94eb"]
+auth_approval -> auth_call [color = "#8f94eb"]
+auth_approval -> auth_close [color = "#8f94eb"]
+auth_approval -> auth_getstate [color = "#8f94eb"]
+auth_usercheck -> _auth_validuser [color = "#96fc6d"]
+auth_usercheck -> login_getclass [color = "#96fc6d"]
+auth_usercheck -> login_getstyle [color = "#96fc6d"]
+auth_usercheck -> login_close [color = "#96fc6d"]
+auth_usercheck -> auth_open [color = "#96fc6d"]
+auth_usercheck -> auth_setitem [color = "#96fc6d"]
+auth_usercheck -> auth_setdata [color = "#96fc6d"]
+auth_usercheck -> auth_verify [color = "#96fc6d"]
+auth_userokay -> auth_usercheck [color = "#3eb09b"]
+auth_userokay -> auth_close [color = "#3eb09b"]
+auth_userchallenge -> _auth_validuser [color = "#0db8d4"]
+auth_userchallenge -> login_getclass [color = "#0db8d4"]
+auth_userchallenge -> login_getstyle [color = "#0db8d4"]
+auth_userchallenge -> auth_open [color = "#0db8d4"]
+auth_userchallenge -> login_close [color = "#0db8d4"]
+auth_userchallenge -> auth_setitem [color = "#0db8d4"]
+auth_userchallenge -> auth_close [color = "#0db8d4"]
+auth_userchallenge -> auth_challenge [color = "#0db8d4"]
+auth_userresponse -> auth_setstate [color = "#cc7ac2"]
+auth_userresponse -> auth_getitem [color = "#cc7ac2"]
+auth_userresponse -> _auth_validuser [color = "#cc7ac2"]
+auth_userresponse -> auth_close [color = "#cc7ac2"]
+auth_userresponse -> auth_setdata [color = "#cc7ac2"]
+auth_userresponse -> auth_getstate [color = "#cc7ac2"]
+auth_userresponse -> auth_check_expire [color = "#cc7ac2"]
+auth_verify -> auth_open [color = "#83192f"]
+auth_verify -> auth_setstate [color = "#83192f"]
+auth_verify -> auth_setitem [color = "#83192f"]
+auth_verify -> auth_getitem [color = "#83192f"]
+auth_verify -> _auth_validuser [color = "#83192f"]
+auth_verify -> auth_set_va_list [color = "#83192f"]
+auth_verify -> auth_call [color = "#83192f"]
+auth_clean -> auth_clrenv [color = "#759227"]
+auth_clean -> auth_setitem [color = "#759227"]
+auth_close -> auth_setenv [color = "#4a5505"]
+auth_challenge -> _auth_validuser [color = "#5e3ac3"]
+auth_challenge -> auth_getvalue [color = "#5e3ac3"]
+auth_setitem -> auth_setitem [color = "#e67693"]
+auth_setitem -> _auth_validuser [color = "#e67693"]
+auth_check_expire -> auth_setpwd [color = "#739550"]
+auth_check_change -> auth_setpwd [color = "#902d9d"]
+auth_call -> _auth_next_arg [color = "#a9e6c9"]
+auth_call -> _auth_spool [color = "#a9e6c9"]
+auth_call -> _add_rmlist [color = "#a9e6c9"]
+auth_call -> auth_clrenv [color = "#a9e6c9"]
+_auth_spool -> _recv_fd [color = "#977e1c"]
+login_getstyle -> login_getcapstr [color = "#51a344"]
+login_getcapsize -> strtolimit [color = "#97959e"]
+gsetrl -> login_getcaptime [color = "#35d53a"]
+gsetrl -> login_getcapsize [color = "#35d53a"]
+gsetrl -> login_getcapnum [color = "#35d53a"]
+setclasscontext -> login_getclass [color = "#5b8e44"]
+setclasscontext -> setusercontext [color = "#5b8e44"]
+setclasscontext -> login_close [color = "#5b8e44"]
+setusercontext -> login_getclass [color = "#7eb75f"]
+setusercontext -> login_close [color = "#7eb75f"]
+setusercontext -> login_getcapnum [color = "#7eb75f"]
+setusercontext -> setuserenv [color = "#7eb75f"]
+setusercontext -> setuserpath [color = "#7eb75f"]
+setuserpath -> login_setenv [color = "#35ed7d"]
+setuserenv -> login_setenv [color = "#a1aa6a"]
+login_setenv -> expandstr [color = "#502c54"]
+strtosize -> multiply [color = "#a61402"]
+strtosize -> strtosize [color = "#a61402"]
+strtolimit -> strtosize [color = "#c987ba"]
+}
diff --git a/content/posts/how-bsd-authentication-works/graph.svg b/content/posts/how-bsd-authentication-works/graph.svg
new file mode 100644
index 0000000..94f22d2
--- /dev/null
+++ b/content/posts/how-bsd-authentication-works/graph.svg
@@ -0,0 +1,856 @@
+
+
+
+
+
diff --git a/content/posts/how-bsd-authentication-works/index.org b/content/posts/how-bsd-authentication-works/index.org
new file mode 100644
index 0000000..f0623c2
--- /dev/null
+++ b/content/posts/how-bsd-authentication-works/index.org
@@ -0,0 +1,2811 @@
+#+TITLE: How BSD Authentication Works
+#+DATE: 2021-10-18T17:27:13-04:00
+#+DRAFT: true
+#+SHOWTOC: true
+#+DESCRIPTION: A walkthrough of how OpenBSD's BSD Auth framework functions
+#+TAGS[]: openbsd security
+#+KEYWORDS[]: openbsd security
+#+SLUG:
+#+SUMMARY:
+
+#+ATTR_HTML: :title OpenBSD Internals
+#+ATTR_HTML: :alt OpenBSD mascot cutaway view with spinning gears inside
+[[file:openbsd_internals.gif]]
+
+* History
+ :PROPERTIES:
+ :CUSTOM_ID: history
+ :END:
+
+ The way OpenBSD authenticates users is quite different from other
+ Unix-like operating systems. Most other systems like AIX, Solaris,
+ Linux, the other BSDs, and MacOS, use a framework called [[https://en.wikipedia.org/wiki/Pluggable_authentication_module][Pluggable
+ Authentication Module]] (PAM). The two main implementations are [[http://www.linux-pam.org/][Linux
+ PAM]] and [[https://www.openpam.org/][OpenPAM]]. PAM modules are created as dynamically loaded
+ shared objects, which communicate using a combination of common and
+ implementation specific 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]]). It's
+ 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]] file. While it can
+ be flexible, it's highly complex and very easy to mis-configure,
+ leaving you open to strange and hard to track down authentication
+ bugs. On top of that, the fact that it's a shared library means that
+ any vulnerability in a poorly vetted authentication module gives
+ attackers direct access to the internals of your application. Author
+ Michael W. Lucas said it best when he described PAM as
+ [[https://www.youtube.com/watch?v=-CXp3byvI1g][unstandardized black magic]].
+
+ OpenBSD on the other hand uses a mechanism called BSD
+ Authentication. It was originally developed for a now-defunct
+ 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 then 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. The module 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)=]].
+
+* Documentation
+ :PROPERTIES:
+ :CUSTOM_ID: documentation
+ :END:
+
+ 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)=]].
+
+ Click on any function prototype in this post to see its definition.
+
+ I've also created a [[#graph][graph]] at the bottom of the post to help
+ visualize the function calls.
+
+ All code snippets from this blog post belong to the OpenBSD
+ contributors. Please see the [[#copyright][Copyright]] section for details.
+
+* BSD Auth Modules
+ :PROPERTIES:
+ :CUSTOM_ID: modules
+ :END:
+
+ Modules are located in =/usr/libexec/auth/= with the naming
+ convention =login_
+#+end_export
diff --git a/content/posts/how-bsd-authentication-works/notes.org b/content/posts/how-bsd-authentication-works/notes.org
new file mode 100644
index 0000000..9bd67d4
--- /dev/null
+++ b/content/posts/how-bsd-authentication-works/notes.org
@@ -0,0 +1,83 @@
+* Notes
+ https://web.archive.org/web/20170327150148/http://www.penzin.net/bsdauth/
+ - In the man page for [[https://man.openbsd.org/auth_subr.3#auth_call][=auth_call=]] it says
+ #+begin_src text
+ 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_src
+
+ However I don't see this enforced anywhere, I even wrote a small test
+ script to prove it.
+
+ #+CAPTION: =authfail.c=
+ #+begin_src c
+ #include
+ #include
+ #include
+ #include
+
+ int main(void) {
+ auth_session_t *as;
+
+ as = auth_open();
+ auth_call(as, "/home/dante/auth_tests/authtest/test", "hello", NULL);
+ auth_close(as);
+ }
+ #+end_src
+
+ Changing ="/home/dante/auth_tests/authtest/test"= to the location
+ of the =test= binary.
+
+ #+CAPTION: =test.c=
+ #+begin_src c
+ #include
+
+ int main(void) {
+ printf("Hello! I don't have a secure path!\n");
+ return 0;
+ }
+ #+end_src
+
+ #+CAPTION: =Makefile=
+ #+begin_src makefile
+ CFLAGS = -Wall -Wextra
+
+ run: authfail test
+ ./authfail
+
+ authfail: authfail.c
+ $(CC) -o $@ $(CFLAGS) $<
+
+ test: test.c
+ $(CC) -o $@ $(CFLAGS) $<
+ #+end_src
+
+ Which results in the following:
+
+ #+begin_src text
+ $ pwd && ls -l && make
+ /home/dante/auth_tests/authtest
+ total 12
+ -rw-r--r-- 1 dante dante 143 May 30 19:20 Makefile
+ -rw-r--r-- 1 dante dante 248 May 29 19:30 authfail.c
+ -rw-r--r-- 1 dante dante 115 May 29 19:22 test.c
+ cc -o authfail -Wall -Wextra authfail.c
+ cc -o test -Wall -Wextra test.c
+ ./authfail
+ Hello! I don't have a secure path!
+ #+end_src
+
+ - The manpage also says the path is limited to =/bin/= and =/usr/bin=,
+ which is also not the case.
+
+ - The man page describes the interface for =auth_getitem= is in the
+ format of =AUTH_
- =, but in reality it is =AUTHV_
- =.
+
+ # Ask jcs about the file descriptor situation, I don't understand it
+ # after reading both the man page and source.
+
+ - The [[#auth_getchallenge][=auth_getchallenge=]] function in the [[https://man.openbsd.org/auth_subr.3#auth_getchallenge][=auth_subr(3)=]] man page
+ doesn't seem to exist in the source code.
+
+** TODO How are these configured in login.conf?
diff --git a/content/posts/how-bsd-authentication-works/openbsd_internals.gif b/content/posts/how-bsd-authentication-works/openbsd_internals.gif
new file mode 100644
index 0000000..5088082
Binary files /dev/null and b/content/posts/how-bsd-authentication-works/openbsd_internals.gif differ
--
cgit v1.2.3