WRSomsky
UW Physics & Astronomy Linux Guru

Using the XLDAP Prototype

From a basic install of CentOS 7,

From a basic install of CentOS 7,

Required RPMS

yum install nss-pam-ldapd pam_krb5

../../lib/Sfml.cgi:

#!/usr/bin/perl
use warnings ;
use strict ;

##  /n/n		paragraph break
##  =:: Title		page title
##  === Header1		h1 header
##  ==== Header2	h2 header
##  ===== Header3	h3 header
##  ====== Header4	h4 header
##  =<url		url link
##  =<url> text		url link w/ text
##  =<<<file		include boxed verbatim file
##  =<<<file> tag	include boxed verbatim file w/ tag
##  =---		begin boxed verbatim (end w/ =---)
##  =--- title		begin boxed verbatim (end w/ =---) w/ title
##  =--			begin white verbatim (end w/ =--)
##  =-- title		begin white verbatim (end w/ =--) w/ title
##  =AUTOINDEX		insert directory autoindex (needs .htaccess support)

use POSIX ;
use IO::Handle ;
use File::stat ;
use CGI qw[ escapeHTML ] ;

# --- CGI Framework ---

my $cgi ;

BEGIN # Emit header immediately & redirect STDERR to catch errors...
  {
  $cgi = CGI->new ;
  print $cgi->header ;
  STDOUT->autoflush(1) ;
  STDERR->autoflush(1) ;
  open STDERR, '>&', STDOUT or die ;
  }

# --- Load Template and StyleSheet from <DATA> ---

my @stylesheet ;
my @template ;

while (<DATA>)
  {
  chomp ;
  ## last		if /^__END__/ ;
  push @template, $_	if /^__TEMPLATE__/.../^__/ and !/^__/ ;
  push @stylesheet, $_	if /^__STYLESHEET__/.../^__/ and !/^__/ ;
  }

# --- Stat & Open SFML File ---

my $sfml_file	= $ENV{'PATH_TRANSLATED'}
		    || $ARGV[0] or die "No input specified...\n" ;
my $sfml_stat	= stat $sfml_file or die "Cannot stat $sfml_file: $!\n" ;
my $sfml_date	= strftime "%F", localtime $sfml_stat->mtime  ;
open SFML, '<', $sfml_file or die "Cannot open $sfml_file: $!\n" ;

# --- Breadcrumb Links ---

my @breadcrumbs ;
my $req = $ENV{'REQUEST_URI'} ;
$req =~ s|/+|/|g ; $req =~ s|^/|| ;
my $link = "" ;
foreach (split '/', $req)
  {
  $link .= "/$_" ;
  push @breadcrumbs, "<a href=$link>$_</a>" ;
  }
$breadcrumbs[0] = "<a href=/somsky>WRSomsky</a>" ;

# --- Process SFML File ---

my $title ;
my @content ;

sub cont { push @content, @_ ; }

my $par = 0 ;
sub par { cont "<p>" unless $par ; $par = 1 ; } # begin paragraph
sub rap { cont "</p>\n"  if $par ; $par = 0 ; } # end paragraph

my $verb = 0 ;

sub verb
  {
  cont "<p class=tag>@{[shift]}</p>" if defined $_[0] ;
  cont "<pre>" ;
  $verb = 1 ;
  }

sub verbw
  {
  cont "<p class=tag>@{[shift]}</p>" if defined $_[0] ;
  cont "<pre class=w>" ;
  $verb = 1 ;
  }

sub brev
  {
  cont "</pre>" ;
  $verb = 0 ;
  }

sub verbfile {
  my $file = shift ;
  my $tag  = shift ;
  $tag ||= $file ;
  my $path = $ENV{'PATH_TRANSLATED'} ;
  $path =~ s|[^/]*$|| ; $path .= $file ;
  verb "<a href=$file>$tag</a>:" ;
  if (open FILE, $path) {
    while (<FILE>) { cont escapeHTML $_ ; }
    }
  else {
    cont "<span style='color:#cc0000'>" ;
    cont " --- Cannot open '$file' for display --- \n" ;
    cont " Path: $path " ;
    cont "</span>\n" ;
    }
  close FILE ;
  brev ;
  }

sub autoindex
  {
  use LWP::Simple ;
  my $request = $ENV{'REQUEST_URI'} ;
  $request =~ s|/[^/]*$|?AUTOINDEX| ;
  foreach (split /\n/, get "http://".$ENV{'SERVER_NAME'}."//".$request)
    {
    cont "$_\n" if m|<pre>|..m|</pre>| and not m|</pre>| ;
    }
  cont "</pre>" ; # do it this way to drop trailing <hr>
  }

while (<SFML>)
  {
  chomp ;
  if (0) {}

  elsif ($verb and /^=---?/)	{ brev ; }
  elsif ($verb)			{ cont escapeHTML "$_\n" ; }
  elsif (/^=---\s*(.*)/)	{ rap ; verb  $1 ; }
  elsif (/^=--\s*(.*)/)		{ rap ; verbw $1 ; }

  elsif (/^=AUTOINDEX/)		{ autoindex ; }

  elsif (/^=<<<\s*([^>]*)>(.*)/)	{ verbfile ($1,$2) ; }
  elsif (/^=<<<\s*(.*)/)	{ verbfile ($1) ; }

  elsif (/^=<\s*([^>]*)>(.*)/)	{ cont "<a href=$1>$2</a>\n" ; }
  elsif (/^=<\s*(.*)/)		{ cont "<a href=$1>$1</a>\n" ; }

  elsif (/^======\s*(.*)/)	{ rap ; cont "<h4>$1</h4>\n" ; }
  elsif (/^=====\s*(.*)/)	{ rap ; cont "<h3>$1</h3>\n" ; }
  elsif (/^====\s*(.*)/)	{ rap ; cont "<h2>$1</h2>\n" ; }
  elsif (/^===\s*(.*)/)		{ rap ; cont "<h1>$1</h1>\n" ; }
  elsif (/^=::\s*(.*)/)		{ $title = $1 if not defined $title ; }

  elsif (/^\s*$/)		{ rap ; }
  else				{ par ; cont "$_\n" ; }
  }

rap ; # close terminal paragraph, if any

# --- Output HTML Page ---

print $cgi->start_html (
  -title => $title,
  -style => { -code => join "\n", @stylesheet }, 
  ) ;

foreach (@template)
  {
  s/%%LASTMOD%%/$sfml_date/ ;
  s/%%BREADCRUMBS%%/join "::", @breadcrumbs/e ;
  s/%%CONTENT%%/join '', @content/e ;
  print "$_\n" ;
  }

print $cgi->end_html ;

__DATA__ # ====================================================================

__TEMPLATE__ # ----------------------------------------------------------------

<div id=sheet>
<div id="masthead">
<table>
<tr class=banner1><td colspan=2>WRSomsky</td></tr>
<tr class=banner2><td colspan=2>UW Physics &amp; Astronomy Linux Guru</td></tr>
<tr class=nav>
  <td class=crumbs>%%BREADCRUMBS%%</td>
  <td class=mtime>%%LASTMOD%%</td>
</tr>
</table>
</div>
<div id="content">
%%CONTENT%%
</div>

__STYLESHEET__ # --------------------------------------------------------------

html		{  font-family: "Open Sans",Helvetica,Arial,sans-serif ; }

body			{  background: #dd9933 ; margin: 0 ; padding: 1em; }

div#sheet		{  margin: 0px auto 0px auto ; padding: 1.5em ; }
div#sheet		{  box-shadow: 0.5em 0.5em 0.25em #573a0f ; }
div#sheet		{  background: #faebd7 ; }
div#sheet		{  max-width: 860px ; }

div#masthead		{ margin-bottom: 2.5em ; }
div#masthead table	{ width: 100% ; }
div#masthead table	{ border: 0 ; border-collapse: collapse ; }
div#masthead tr		{ background: #aaaaaa ; }
div#masthead tr.nav	{ background: #555555 ; }
div#masthead tr.nav	{ color: #cccccc ; }
div#masthead a		{ text-decoration: none ; }
div#masthead a:link	{ color: #cccccc ; }
div#masthead a:visited	{ color: #cccccc ; }
div#masthead a:hover	{ color: #90ff90 ; text-decoration: underline ; }
div#masthead a:active	{ color: #ffff00 ; text-decoration: underline ; }
div#masthead td.crumbs	{ width: 100% ; }

div#masthead tr.banner1 { font-size: 200% ; font-weight: bold ; }
div#masthead tr.banner2 { font-size: 120% ; font-weight: normal ; }
div#masthead tr.banner1 { line-height: 1 ; }
div#masthead tr.banner2 { line-height: 1 ; }

div#masthead tr.banner1 td { margin: 0px ; padding: 10px 10px  0px 10px ; }
div#masthead tr.banner2 td { margin: 0px ; padding:  2px 10px  8px 10px ; }
div#masthead tr.nav	td { margin: 0px ; padding:  2px 10px  2px 10px ; }

div#content p.tag	{ margin-bottom: 0.1em ; font-size: 86% ; }
div#content p.tag + pre	{ margin-top: 0em ; }

div#content pre {
  background: #dddddd ;
  font-family: monospace ;
  border: thin solid #777777 ;
  padding: 0.25em 0.50em ;
  white-space: pre ;
  }

div#content pre.w {
  background: #faebd7 ;
  padding: 0em 0em ;
  border: none ;
  }

__END__ # =====================================================================
__END__ # =====================================================================
__END__ # =====================================================================

Verbatim:

This is some < verbatim text
    indented & stuff

Verbatim-w:

This is some < verbatim text
    indented & stuff

Tagged:

tag

Some verbatim w/ a tag... & stuff

Tagged:

tag

Ditto white Some verbatim w/ a tag... & stuff

Include a file verbatim, w/ altname

Client/ldap.conf:

uri		ldaps://xldap.phys.washington.edu:636
base		ou=u_somsky,dc=XLDAP
TLS_REQCERT	allow

Include a file verbatim, w/ altname

/etc/nsswitch.conf:

passwd:     files ldap
shadow:     files ldap
group:      files ldap
netgroup:   files ldap
#--
hosts:      files dns
#--
aliases:    files
automount:  files
bootparams: files
ethers:     files
netmasks:   files
networks:   files
protocols:  files
publickey:  files
rpc:        files
services:   files

A link: http://cnn.com with text after

A link w/ text Donnie calls this FAKE! with text after


/etc/openldap/ldap.conf:

uri		ldaps://xldap.phys.washington.edu:636
base		ou=u_somsky,dc=XLDAP
TLS_REQCERT	allow

/etc/nslcd.conf:

uid		nslcd
gid		ldap

tls_reqcert	allow
uri		ldaps://xldap.phys.washington.edu:636
binddn		cn=reader,ou=bindDNs,ou=u_somsky,dc=XLDAP
bindpw		reader

bind_timelimit	30
timelimit	30
idle_timelimit	3600

filter	group	(objectClass=posixGroup)
base	group	ou=xldapGroup,ou=u_somsky,dc=XLDAP

filter	passwd	(objectClass=xldapPosixAccount)
base	passwd	ou=xldapAccount,ou=u_somsky,dc=XLDAP
map	passwd	uidNumber	uwUidNumber
map	passwd	gidNumber	uwGidNumber

   map	passwd	gecos		uwDisplayName
## map	passwd	gecos		unitDisplayName

## map	passwd	homeDirectory	uwHomeDirectory
## map	passwd	homeDirectory	unitHomeDirectory
   map	passwd	homeDirectory	"/local/users/$uid"

## map	passwd	loginShell	uwLoginShell
## map	passwd	loginShell	unitLoginShell
   map	passwd	loginShell	"${uwLoginShell:-/bin/tcsh}"

## ---------------------------------------------------------
## See nslcd.conf(5) for info on maps and map expressions...
## ---------------------------------------------------------

/etc/krb5.conf:

[logging]
  kdc = FILE:/var/log/krb5kdc.log
  default = FILE:/var/log/krb5libs.log
  admin_server = FILE:/var/log/kadmind.log

[libdefaults]
  default_realm = NETID.WASHINGTON.EDU

[realms]

[domain_realm]

[appdefaults]

/etc/pam.d/system-auth-xldap:

#%PAM-1.0

# required   = [default=bad    success=ok   new_authtok_reqd=ok ignore=ignore]
# requisite  = [default=die    success=ok   new_authtok_reqd=ok ignore=ignore]
# optional   = [default=ignore success=ok   new_authtok_reqd=ok  ]
# sufficient = [default=ignore success=done new_authtok_reqd=done]

auth required				pam_env.so
auth sufficient				pam_unix.so try_first_pass
auth requisite				pam_succeed_if.so uid >= 1000
auth sufficient				pam_krb5.so use_first_pass
auth required				pam_deny.so

password requisite			pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password sufficient			pam_unix.so sha512 shadow try_first_pass use_authtok
password requisite			pam_succeed_if.so uid >= 1000
password sufficient			pam_krb5.so use_authtok
password required			pam_deny.so

account required			pam_unix.so broken_shadow
account sufficient			pam_succeed_if.so uid < 1000 quiet
account required			pam_ldap.so
account optional			pam_krb5.so
account required			pam_permit.so

session optional			pam_keyinit.so revoke
session required			pam_limits.so
session optional			pam_systemd.so
session [success=1 default=ignore]	pam_succeed_if.so service in crond quiet use_uid
session required			pam_unix.so
session optional			pam_ldap.so
session optional			pam_krb5.so