Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

Also see [[AdvancedOptions]]
<div class='header' role='banner' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' role='navigation' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' role='navigation' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' role='complementary' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea' role='main'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected {color:[[ColorPalette::PrimaryDark]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:alpha(opacity=60);}
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0; top:0;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0 3px 0 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0; padding-bottom:0;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox where print preview displays the noscript content */
<div class='toolbar' role='navigation' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<table border=0>
<tr border=0><TD align=center border=0>
<iframe src="" style="border: 0" width="1000" height="600" frameborder="0" scrolling="no"></iframe>
<BR><B>This calendar is authoritative should there be due date conflicts with other pages on the site</B>

I want project slides.  Save them to your cs407/project directory.

I'll have grades updated on the class website in the next couple of days
 - Let me know if any labs are missing grades
 - I'll accept outstanding labs until noon on Sunday, May 10.

~VMs will be deleted on Friday, May 15
 - Let me know if you need them longer or would like them exported.

If you'd like, we can talk about the final after presentations are done today.
!! CollapseTiddlersPlugin
^^Author: Bradley Meck^^

|ELS 2/24/2006: added fallback to "CollapsedTemplate if "WebCollapsedTemplate" is not found |
|ELS 2/6/2006: added check for 'readOnly' flag to use alternative "WebCollapsedTemplate" |


config.commands.collapseTiddler = {
text: "fold",
tooltip: "Collapse this tiddler",
handler: function(event,src,title)
var e = story.findContainingTiddler(src);
if(e.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){
var t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }
if(e.getAttribute("template") != t ){

config.commands.expandTiddler = {
text: "unfold",
tooltip: "Expand this tiddler",
handler: function(event,src,title)
var e = story.findContainingTiddler(src);

config.macros.collapseAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"collapse all","",function(){
if(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE])
var t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }

config.macros.expandAll = {
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,"expand all","",function(){
var t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }
if(tiddler.getAttribute("template") == t) story.displayTiddler(null,title,tiddler.getAttribute("oldTemplate"));

config.commands.collapseOthers = {
text: "focus",
tooltip: "Expand this tiddler and collapse all others",
handler: function(event,src,title)
var e = story.findContainingTiddler(src);
if(tiddler.getAttribute("template") != config.tiddlerTemplates[DEFAULT_EDIT_TEMPLATE]){
var t = (readOnly&&store.tiddlerExists("WebCollapsedTemplate"))?"WebCollapsedTemplate":"CollapsedTemplate";
if (!store.tiddlerExists(t)) { alert("Can't find 'CollapsedTemplate'"); return; }
if (e==tiddler) t=e.getAttribute("oldTemplate");
// ELS 2006.02.22 - removed this line. if t==null, then the *current* view template, not the default "ViewTemplate", will be used.
// if (!t||!t.length) t=!readOnly?"ViewTemplate":"WebViewTemplate";
<div><div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler  permalink references jump newHere expandTiddler collapseOthers'></div>
<div class='title' macro='view title'></div></div>
~CS407 & ~NCS522 crosslist

!!!~NCS522 course title & description mismatch
Network Administration:
This course is designed to provide students with the foundations, advanced level knowledge and skills in system administration in the UNIX and MS Windows server environments. Students will gain an understanding of core system administration topics and techniques and acquire the ability to identify major tasks in administering server systems, manage primary services on the system, employ basic security and performance tuning techniques, and troubleshoot common system problems.

*[[Command line summary handout|handouts/UnixCommandSummary.pdf]]
*Activate CS account - see directions on your monitor if you're not already logged in.
*[[Review Syllabus|handouts/CS407Syllabus.pdf]]
*Sample [[Academic Integrity Contract|handouts/Academic_Integrity_Contract.pdf]]
*Quick tour of class website
**Grades on class web site - let me know if you don't want yours posted.
**Outline / Projects / Calendar
**Double arrows on the far right will expand a menu.  The search box only allows for a single word.

!!!Full Disclosure:
* You must be familiar with UNIX and comfortable on the command line.  You cannot competently manage something if you aren't first able to use it.  I expect everyone to already be comfortable UNIX users.
* This will be a very hands on class, with a strong practical component to augment reading and in class discussion.  You will be assigned an assignment to read about a topic, we will discuss it, and then do it.
* SUNY has adopted the [[Carnegie Credit Hour|]], which defines one credit hour as 50 minutes of in-class instruction and two hours of work outside of the classroom.  A four credit hour course thus requires 8 hours per week outside of the classroom.
* This class will be a lot of work and at times fast-paced and challenging.  Expect a decent amount of reading and a graded homework assignment every class.
* If I'm going too fast, please let me know and slow me down.  I have a bad habit of speeding up if everyone is quiet.

Unix Resources:
*[[Command line summary handout|handouts/UnixCommandSummary.pdf]]
* [[Unix Toolbox|]]
* [[CS307 course notes|]]
* Current ~CS307 Textbook: Harley Hahn's Guide To Unix And Linux (0073133612)
* Alternate UNIX textbook: Your Unix/linux: The Ultimate Guide (0073376205) - more expensive, but more content
* Free UNIX textbook:  [[The Linux Command Line|]]
! Class virtual machines

Our Linux distro will be ~CentOS, the community version of Red Hat Linux.  When reading the textbook, pay particular attention to the Red Hat section.  We are running ~CentOS version 6.6.

Manage your system from virtual console at  Log in with your ~DogNET credentials.
Boot from recovery disc to resolve system problems.

Log in to your VM as root
Change the root password

! Basic UNIX Tools

Basic ~CS307 commands and utilities, but especially:

Standard filters: grep, sed, awk, etc.
vi - vimtutor
 - ssh keys (ssh-keygen)
 - ssh agent
 - tunneling
 - socks proxy

See the [[Table of Commands]]

! Filesystem review

# Change to the directory /opt/pub/classes/cs407/filesystem/ and display its contents
# Display the contents of file1.txt
# Change to dir2/.  Display the contents of the file containing spaces in its name
# Change to dir3/.  Display the contents of the hidden file
# Change to dir4/.  Display the contents of the file named -
# Change to dir5/.  Identify the only file containing human readable content (ASCII text) and display it
# Change to the parent of your current directory 
# Display only the line in file6.txt containing the string millionth
# Change to the directory cs407/filesystem/ located within your instructor's home directory
# Display the lines in file7.txt that are human readable and begin with the character =
# Display the line in file8.txt that occurs only once, without first analyzing the contents of the file.
# Create the directories cs407/filesystem/ within the base of your home directory using a single command 
# Change to your cs407/filesystem/ directory
# Set permissions on your filesystem/ directory so no other users on the system can access it.
# Copy the contents of the /opt/pub/classes/cs407/filesystem/ directory to yours
# Change to the directory dir10/ and rename the oddly named file to file10.txt
# Remove extra characters from file11.txt so we are only left with proper text
# Display the decoded content of file12.txt, where all lowercase and uppercase letters have been rotated by 13 positions.
# Display .cshrc and .login files from undergraduate user home directories which are not symbolic links.
# Extract the names from file13.txt, displaying them in Lastname, Firstname format.  After reviewing your output, save it to file13-names.txt
# Remove the filesystem directory and all of its contents
# Create a symbolic link within your cs407 pointing to the filesystem directory in the /opt/pub/ filesystem
# Create atlantis TFTP directories
Continue from here:
# Set up a new server for printing:
## Copy /etc/printcap file from fang
## Generate spool directories
## Test printing
## Terminate the printer daemon when we're finished
# The bzip2 compressed text file file14.txt.bz2 contains connection log information for the CS network.  Analyze this log file and display only outbound SSH traffic from the host gibson.
## First display the first 10 lines of this file to observe the data format
## Adjust the command string to display only the requested lines
# Display the  /etc/printcap  file with instances of __printserver__  changed to  __smbserver__
## Restrict your substitution to only lines containing the string __rm=__
# file15.txt contains MAC addresses for a PC lab in Donovan in Cisco format.  These MAC addresses were just pulled from a Cisco switch.  The ~MACs need to be extracted, converted to the standard format, and inserted into a wakeonlan command string.  Devise a command string or vi command which will accomplish this.
# On directory1, check in to fossil all files except for crontab
# On champ, resolve all IP addresses in table 2

 * Some problems selected from the [[Bandit Challenge|]]

! Assignment

Make sure you are able to properly use basic unix tools.

Become familiar with using your VM.  Next week we will configure networking and bring it fully online.
Become familiar with this class website, the [[CS website|]], particularly the [[CS help docs|]]

Make sure you can access fang from home.  SSH Windows client:  [[Putty|]].  Let me know if you cannot  __before__ the next class.  Hostname =

<<tiddler [[Lab 00 - Connect to fang]]>>

<<tiddler [[Lab 01 - UNIX Refresher]]>>

Review Chapter 1 - Where to start (basic intro to textbook and linux)

! Extra information

Chapter 6 - The Filesystem
Chapter 14 - TCP/IP Networking
Chapter 15 - Routing

! Old Business

- Project proposals
- {{File{/etc/resolv.conf}}}

! Today's Material

!! More DNS

[[RFC 1033|]] - Domain Administrators Operations Guide

!!! Logging

Bind has support for extensive logging of the service and all data transactions
* Bind service messages
** Logged via syslog to /var/log/messages
* Bind data logging
** Logged directly to the files
** Logging categories:
*** All queries
*** Query errors
*** RPZ responses
*** Zone Transfers
*** Many others
** [[Complete logging syntax|]]
** Logging Channels
*** syslog (also specify facility and severity)
*** Directly to a file

!!! Extra commands

* {{Command{rndc}}}
** This is the most important one to know
*** {{Command{rndc}}} - Executed by itself will display sub-commands
*** {{Command{rndc reload}}} - Reload the zone without restarting the service
*** {{Command{rndc dumpdb}}} - Dump cache(s) to the dump file (named_dump.db)
*** {{Command{rndc flush}}} - Flushes all of the server's caches.
*** {{Command{rndc querylog //newstate//}}} - Enable / disable query logging
* named-checkconf - Validate the named.conf file
* named-checkzone - Validate a zone
* named-compilezone - Compile a zone with additional verification
* The perils of {{Command{service named restart}}}

!!!! Zone updates:
Don't forget to update your serial number!
* Notifications are broadcast to slave NS upon serial increment
* Slave NS will then pull a zone transfer
* Records may be stale if you forget to increment the SOA serial

# {{Command{tail -f /var/log/messages}}}.  Either run in a separate screen pane or suspended to the backgroup
# rndc reload
# Observe logs

!!!! Bind configuration changes:
# {{Command{tail -f /var/log/messages}}}.  Either run in a separate {{Command{screen}}} pane or suspended to the background
# {{Command{named-checkconf}}}  ''or''  {{Command{service named check}}}
# {{Command{service named restart}}}

!!! Review our DNS servers
* Review {{Host{}}} config
* Make sure zone transfers are happening
** Add some logging 
** make a change to our zones
** reload
** view logs
* Test on campus lookups
** toggle query log
* Test off campus lookups

!!! Reverse Zones
* Example zone:  ''36.103.10.~IN-ADDR.ARPA.''
* Zones can only be for Class A, B, or C networks.
* Any domain can point to anyone's IP address, regardless of IP ownership
* Only the owner of the IP block can point back to a domain
* Best practices require a reverse zone entry for each forward zone entry
* This can be used to show legitimacy.  
* Some mail servers require a proper reverse record for incoming mail.
* We cannot subdivide the class C zone for delegation.  I'll have to pull your data via zone transfer and generate the complete ''36.103.10.~IN-ADDR.ARPA zone.''
* Since we're not performing zone transfers of the reverse zones, remove the {{Host{}}} NS record.

!!! Zone Apex 
* Also known as a naked domain
* What will your domain itself resolve to?

!!! DNS Validation:

Using dig
* See available options with {{Command{dig -h}}}
* Don't forget the -x for reverse queries
* perform zone transfer to test data
** Compare results between your server and the slave
* see TTL and cache time remaining
* dig errors
** NXDOMAIN - No records for any type
** NODATA - No records for the requested type  (displayed as NOERROR with no answer section)
** REFUSED - The server is refusing our connection likely due to recursion being requested.

!! Additional Records

!!! MX
* mail exchanger identifies which systems to send mail to
* are weighted by priority for multiple mail servers
* Must point to an A record host name
* dig mx

!!! TXT
* create text string records in DNS
* Useful for publishing additional information about a zone or a host

!!! DNS email blacklists
* Take a look at mail logs
* rbldnsd and local zones

!!! DNS domain firewalling with RPZ
* RPZ: Response Policy Zone
* Take a look at the config and zone on ns0
* Block access to certain domains
* Prevent malware from getting on systems by blocking their associated domains
* Disrupt command and control channels for already infected systems
* Many options for how to handle target domains:  [[Zytrax Site|]]
* Published lists are available similar to anti-spam lists:

!!! DNS Sinkholes
* figure out domains used by botnets for C&C and take them over
* typically through domain expiration
* wait and see who connects

!!! DNS Security Extensions (DNSSEC)
* Uses public key crypto to authenticate the zone data's origin and verify integrity
** One key to sign (private key)
** One key to verify (public key)
** Keys will expire and must be periodically rolled 
* Relies on a chain of trust
** Trust is chained similar to NS delegation
* Implementation began with the edu TLD in 2010 and has since included the other ~TLDs
* Not all registrars support it.  ~GoDaddy does.
** A static record must be published upstream similar to the NS glue records.
* Zones must be resigned after each change is made
** Otherwise, minimally the SOA record will not validate after the serial is updated

!!! SSL certificates
* ~DNS-based Authentication of Named Entities (DANE)
* Publish information associated with SSL certificates in DNS
* Useful for determining whether a certificate can be trusted
* [[RFC 6698|]]

* SSH Fingerprints

!!! Cache poisoning
* Trick a caching name server into storing a bad record with a long TTL
* Anyone that asks for that record get the malicious IP address
* For example, get it to cache: IN A //attackers_ip//
* Kaminsky DNS bug - very successful cache poisoning attack

!!! Passive DNS
* Log DNS questions and answers for future analysis
* Centralize this data
* Find bad domains by looking for common A records
* Or by looking at which domains are hosted by bad name servers
* Build our blocked domains lists from this data

!!! DNS walking of the reverse zones to discover content
* Something like this: {{Command{nmap -sL}}}

!!! dnscat
* Covert channel for building a tunnel or exfiltrating information
* like netcat, but hides the data in DNS requests
* very easy to evade detection this way
* Want to hide your SSH session ?

!!! Views
* Respond to a DNS query based on the client location.
** Internal and External views
** Respond with a public IP for an external host or an internal IP for an internal one.
** Don't publish internal only records in external DNS

!!! Command execution
* Have a script query DNS for commands to run.  Either examine the value of an A record and run a command from a predefined list based on the IP address returned or run a command presented in a TXT record.

!!Additional reading
 - kaminsky DNS bug
 - get familiar with the dig command
 - EXPOSURE: Finding Malicious Domains Using Passive DNS Analysis -

! Assignment:

!! Reading
* ~SysAdmin Chapters 4 and 7

<<tiddler [[Lab 14 - Additional DNS records]]>>

! Material - Access control & user management

''Authentication'' - 
''Authorization'' - 

!! Access control (Chapter 4)

!!! From the beginning unix maintained a multi-user system
* All objects (files & processes) have owners
* A user owns new objects they create 
* The administrative user (root) can act as the owner of any object
* Only root can perform most administrative tasks

!!! Groups
* The filesystem has a more sophisticated access control system
* Each file has a user owner and a group owner
* Permissions can be set so group members may have their own set of access controls (rwx)
* Groups can be harnessed to control access to the system

!!! root (uid 0)
* The root user is the standard unix superuser account
* There's nothing special about the user name - it's all in the uid number
* Unix systems track everything by number:  process ~IDs, device ~IDs, IP addresses, uid, and gid
* We prefer names over numbers

!!! Privilege separation 
* superuser (uid 0)
* normal users
* service accounts
* nobody or daemon accounts
* principle of least privilege

!!! Privilege escalation
* Limit direct access to the root account
* Privilege separation - Only obtain superuser privileges when you need them
* Don't always operate as root
* Instead log in as a regular user and escalate when needed
** {{Command{su}}} command - Substitute user
*** Change the effective userid to another system user
*** Real id is the userid you log in as, the user id associated with the process that created the current process
*** Effective id is one the system uses to determine whether you have access to a resource
*** {{Command{su [username]}}}  - Change to another user, simulating a full login.  The current shell environment will not be inherited.
*** {{Command{su - [username]}}}  - Change to another user, inheriting the current shell environment
** {{Command{sudo}}} - Allow elevated privileges on a limited scale (per command)
*** Display what you are allowed to access via sudo: {{Command{sudo -l}}}
*** {{Command{sudo //command//}}} - Run a command as another user (defaults to the root user)
*** {{Command{sudoedit //file//}}} - Edit a file as another user (defaults to the root user)
*** {{Command{visudo}}} - To edit the sudoers file.  Will lock the file and perform syntax checks
*** sudoers file: /etc/sudoers
** Control with user or group permissions
* Both will log escalation events
** su will log when a unprivileged user switches to another user
** sudo/sudoedit will log each command executed or file modified
* setuid bit 
** set ID upon execute
** An extra permission bit that can be set with chmod 
** The program will run as the user who owns the file.
** Examples:  passwd and crontab commands

!!! Finer grained access controls
* ~SELinux and mandatory access controls (MAC)
** Enabled by default in ~CentOS
** ~SELinux will cause us problems if we don't either configure or disable it
** Controlled by the {{Command{setenforce}}} command for current boot
** and by the /etc/selinux/config file on boot
* Filesystem access control lists (~ACLs)
** Finer grained per user access to files
** Controlled by {{Command{setfacl}}} and displayed by {{Command{getfacl}}}
** Active ~ACLs noted with a + at the end of the file permissions list

!!! Verifying users with PAM
* Pluggable Authentication Modules (Section 22.5 on page 908)
* Configuration resides in /etc/pam.d/
* Originally access was determined by just checking passwords against the password files
* Modules are used for user validation and verification
** Can determine who you are
** And if you have permission to access the resource
* Different facilities:
** auth - Authentication functions
** account - Account management functions 
** session - Session handling functions
** password - Password management functions
* Different control flags (required, requisite, sufficient)
** Required - modules are required to succeed.
** Sufficient - success aborts the stack immediately.  Authentication is then granted unless a prior required statement has failed
** Requisite - Failure immediate aborts the stack
** Optional - Login granted on success unless a later module fails
* Examples: 
** {{File{/etc/pam.d/su}}} - limit who can use the su command
*** uid 0 can always run su
*** Change to require wheel group membership
*** Can set to implicitly trust members of the wheel group (dangerous!)
** Dev-net router
*** Allow login to group members
*** Or users with a special tag in their account
* Other pam functions: 
** Pam can also create home directories on first login with pam_mkhomedir
** Check password complexity with pam_crack
** Lock accounts on too many failed attempts with pam_tally

!! Users and Groups (Chapter 7)

!!! Password files
* /etc/passwd
** Contains fields identifying the user
** Used to also contain the password but this was moved elsewhere to hide it from normal users
** Don't leave the old password field (position 2) blank!  If blank, no password is required for login.  Use the placeholder character ''x''.
** You'll see this in the ''files''  VM we're about to create.
* /etc/shadow (Linux) or /etc/master.passwd (~FreeBSD)
** A secure file which contains the password hashes
** Also contains password and account expiration attributes
* Use {{Command{vipw}}} for file locking and verification
** {{Command{vipw}}} will edit the password file
** {{Command{vipw -s}}} will edit the shadow file
* password hashing:
** DES, ~MD5 ($1), Blowfish ($2a), ~SHA256 ($5$), ~SHA512 ($6$)
** {{Command{authconfig &#045;-test | grep hash}}}
** {{Command{authconfig &#045;-passalgo=md5 &#045;-update}}}
** {{File{/etc/sysconfig/authconfig}}}
** {{File{/etc/libuser.conf}}}
** salting
*** Cisco sha hashing (password type 4) vs md5 (type 5)
** Password cracking:
*** John the Ripper
*** hashcat
*** GPU processing makes this all much faster now
*** Protect your hashes!
* uid numbers 
** multiple users with same UID number
** System accounts (UID < 10)
** Service accounts (~UIDs between 10 and 500)
** Users UID > 500 (Linux)

!!! Group file
* /etc/group
* wheel group - special administrator group.  Usually allows extra system access

!!! Shell
* default shell : /bin/bash (Linux) or /bin/tcsh (BSD)
* lockout shell : /sbin/nologin
* Available shells defined in /etc/shells

!!! Locking accounts
 - Replace hash with * or !!
 - change shell to /sbin/nologin
 - /var/run/nologin or /etc/nologin
 - Check out service accounts - should not have passwords or valid shells

!!! New user:
* Use utilities (useradd, userdel, usermod) or edit password files directly
* Create home directory
* Set home dir ownership and permissions
* Set up environment (dot files)
** Copy /etc/skel/ (Linux) or /usr/share/skel/ (~FreeBSD) files to their home directory

!!! Remove or lock user
* Delete or comment lines in password files
** Will no longer be known to the system, but non-destructive
** Change password hash and change shell

!!! Authentication factors:

Multi-factor authentication:
- Passwords are not good enough anymore
- Increase security by combining multiple authentication factors.
- [[Linux Kernel Git Repositories Add 2-Factor Authentication|]]

* Something you know:  passwords
** Should be of sufficient length and complexity to be hard to crack
** Minimum of 10-12 characters
** Should be unique across systems
*** [[Russian Hackers Amass Over a Billion Internet Passwords|]]
*** [[Stolen user data used to access account|]]
*** [[ebay|]] 
** Password Cards:,, etc
** Password vaults
** One-time passwords (OTPW)

* Something you have
** [[DoD CAC card|]]
** [[Google 2 factor|]]
** [[yubikey|]]
** [[RSA SecureID|]]

* Something you are
** biometrics:  fingerprint, retina, voice print, facial.

* Somewhere you are
** Geofencing
** ~GeoIP libraries
** pam_geoip

!!! SSH authentication & increasing security

!!!! ssh keys
* Access systems with keys instead of just passwords for added security
* 1.5 factor authentication:  Slightly better then just passwords
* Create keypairs with ssh-keygen
* Public keys are stored in ~/.ssh/authorized_keys
* Host public keys are stored in ~/.ssh/known_hosts
* ssh-agent & ssh-add : add your ssh keys to the agent to be used for connecting to multiple systems
* pssh - parallel ssh

!!!! sshd configuration
* Host keys
** Host key warning 
* Require SSH keys to access the system (disable password authentication)
* Store SSH public keys locally
* Deny root login
* Require group membership

! Assignment

<<tiddler [[Lab 15 - VM Lockdown - Secure your VMs]]>>

<<tiddler [[Lab 16 - sudo]]>>

<<tiddler [[Lab 17 - Bring the storage server online]]>>

!! Reading

Read ~SysAdmin Chapter 8 - Storage up to section 8.8 on page 246.

!! Additional Reading

PAM:  ~SysAdmin Chapter 22.5 (Page 908)
! Old Business

SSHFP records

! New Material

File storage is a core function of any unix system
Something must store the operating system
Along with any system or user data

Core storage concepts today
 - Various storage layers
 - What we store files on and how we're currently making it available to the system

Additional storage discussion next class
 - Network file systems
 - Additional filesystem types
 - Other ways to store data and make files available to the system
 - swap

!! Storage layers:


Hardware storage devices
 - Storage medium (hdd, flash, optical, tape)
 - How the medium physically attaches to the system (SATA,SAS,USB)
Redundancy (optional): RAID arrays or Volumes

!! Storage Devices

!!! Storage medium:
* Traditional disks: 
** Platter rotation speed in RPM:  5400, 7200, 10k, 15k
** File fragmentation / defrag
* SSD - Solid State Disk
** Faster
** Limited number of writes
** No moving parts
*** No more defragging
*** More reliable
** More expensive per GB
** Data written out in pages.  A memory page must be erased before data is written.  Erase is slower then write.
** TRIM command - erase pages before they're needed to increase performance
** Be sure to align filesystem clusters to SSD pages
*** Align partitions to page boundaries 
* Hybrid drives
** Part SSD / part magnetic platter
* Flash drives / cards
* Optical 
* Tape

!!! Interfaces

* ATA - Advanced Technology Attachment
** PATA - Parallel ATA  (IDE)
*** ATA/133 - 133 MB/s
*** 40 pin, 80 conductor ribbon cable
** SATA - Serial ATA
*** Replaced PATA
*** much higher transfer rates - 6Gb/s (750MB/s)
*** many performance enhancements
*** hot swap
*** better cabling

*SCSI - Small Computer System Interface
** Parallel SCSI
*** Old ribbon cables
*** or daisy chaining of devices
*** Used for connecting disks and early peripherals (tape drives, CD writers, scanners, printers, etc)
*** Bus ends must be terminated to prevent noise by absorbing signals which reach the end of the bus 
*** All devices have a unique target number to identify them on the bus (0 - 15), set by dip switches or jumpers
** SAS - Serial Attached SCSI
*** New standard for enterprise connection
*** Point to point connections instead of chained
*** No longer limited to 16 devices on the bus
*** Connectors compatible with SATA
*** Higher transfer rates - 6 or 12Gb/s
*** SATA price and performance make for good enterprise alternatives
*** Similar connectors and support for SATA drives

* Fibre Channel
** enterprise
** high bandwidth
** speed
** can connect many devices at once

** very slow
** v1: 1.5 Mbit/s or 12 Mbit/s (~Full-Bandwidth)
** v2: ~Hi-Speed - 480Mb/s
** v3:  ~SuperSpeed - 4Gb/s
** v3.1: ~SuperSpeed+ - 10Gb/s
** USB converters for SATA
* Network access - Storage area Network (SAN)
** iSCSI (SCSI over IP)
** Network file system (NFS)

!!! From the operating systems perspective:

Device files in /dev/
Identify the devices:
 - Check {{Command{dmesg}}}
 - Scan {{File{/var/log/messages}}}
 - {{Command{ls /dev/sd*}}}
 - {{Command{ls /dev/xvd*}}}

!!! Disk failure 

Disk failure is increasingly common
* [[Google disk failure research|]]
* [[Backblaze hard drive report|]]
** Drives tend to fail either very early (first few months) or after about 3 years
** Generally there's only a 75% 5 year survival rate
* Traditional hard drives have moving parts
** Drive burn-in - early disk activity to catch failures before actual use
* Solid state 
** Limited number of write cycles
** Wear leveling - distribute wear across the disk
*** Relocation of static data
** Firmware will keep track 
* {{Command{badblocks}}} command  
* SMART Monitoring
* A good backup and disk redundancy strategy will mitigate the effects of disk failure


Combine multiple physical storage devices into a single virtual device.

RAID Levels:
Linear (JBOD): Concatenate all disks into one logical volume
Level 0, 1, 5, 6, 10
Raid can be used to protect against hardware failure, not data corruption or online data loss

!!! Volume groups

Aggregate physical devices to form pools of storage (volume groups)
This pool can be divided into logical volumes for use

Linux LVM
* Allocate space on demand and resize filesystems
* Snapshots
* Does not support raid 5 or 6.  Use linux software raid for redundancy then LVM to assign slices
* Access with pv, vg, lv commands.  ie: lvdisplay
* Thin provisioning:
** Over provisioning
** xen server disk allocation:


Sun zfs
 - A mix of RAID and LVM

!!! Software RAID:
Can monitor and send emails if there are any problems.

Use cfdisk to create partitions then mirror them
mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/xvdb1 /dev/xvdc1

cat /proc/mdstat

mdadm --stop /dev/md0
mdadm --assemble --scan 

mdadm --detail --scan >> /etc/mdadm.conf
mdadm -As /dev/md0

mdadm /dev/md0 -f /dev/xvdc1
cat /proc/mdstat
tail /var/log/messages

mdadm /dev/md0 -r /dev/xvdc1
mdadm /dev/md0 -a /dev/xvdc1

mdadm --stop /dev/md0

Use mdadm to create large raid5 or 6 arrays then LVM to allocate space into partitions

!! Partitions

A fixed-sized division of the storage device

A way to organize files by type or access level.

Traditional partitioning, MBR style
The first sector (512 bytes) of the disk contains the MBR.  First 440 for boot code and next 64 for partition info.
There is a 4 partition limit due to the 64b size constraints
using dd for duplicating systems

The new way: GPT - GUID partition tables
* break 2tb disk barrier
* more then 4 partitions per disk
* partition info stored at beginning and end of the disk (more resilient) 
* protective MBR
** Prevents non-GPT utilities from overwriting GPT partition info
** Allows non-GPT systems to boot GPT disks

fdisk -l

cfdisk for /dev/xvdb

parted / gparted (kali usb boot)

!! Filesystems

The interface between the data and on the disks and the system.  

Linux Filesystem types:
 - extended filesystem - ext
 - ext2 - original and longtime standard
 - extended by new versions: ext3 and ext4

{{Command{mkfs.*}}} - create filesystems

Filesystem mounting
* mount points
* Standard {{Command{mount}}} and {{Command{umount}}} commands
* /etc/fstab file to configure standard filesystems and mount on boot
* {{Command{mount}}}
** {{Command{mount [-t type] [-o option[,option]...] device dir}}}
** {{Command{mount -a }}}
** Mount options
*** rw / ro
*** noexec  (Maybe for /tmp/?)
*** nosuid   (Maybe for /home/?)
*** noauto - Used in fstab to not mount the filesystem on boot
*** remount - remount a filesystem, changing its mount options
* {{Command{umount}}}

fsck - filesystem check
 - journaling speeds things up

Root reserved space
 - 8% of the volume is reserved for root (by default)
 - Users cannot utilize this last 8%

Usage quotas
 - Per user or per group

!!! Other filesystem types:

!!!! ~RAM-backed filesystem

Xen server problem background 
 - Thin provisioning

ramfs - RAM will be used to store files until it is exhausted.  No limit to the size of the filesystem.

tmpfs - Also RAM backed, but a max size can be specified.  Will use swap if physical memory is exhausted.  This filesystem type largely replaces the older ramfs.

{{Command{mount -t //TYPE// -o size=//SIZE// //DEVICE// //MOUNTPOINT//}}}

Note memory usage before creating RAM backed filesystems.  Don't starve your system for resources.
Check total and available memory with the {{Command{free}}} command

! Assignment

!! Prepare www for partitioning:

# cd /opt/src/php-5.6.5
# make clean
# cd /opt/src/httpd-2.2.29
# make clean

!! Read ~SysAdmin Chapter 8 - Sections 8.7 (246) to 8.10 (264) 

<<tiddler [[Lab 18 - Fix SSHFP Records]]>>
<<tiddler [[Lab 19 - Logical Volume Manager]]>>
<<tiddler [[Lab 20 - Move apache logs]]>>
! Old Business

!! LVM Wrap-up

Rearrange web server

Verify permissions on /tmp/

! New Material

!! Unix Warmup

Hardlink usage example: maximus xen ISO collection

!! Outline:  Other filesystem and mount types

* NFS - Network file system
* Fuse - Filesystem in userspace
* bind / nullfs mounts
* Cloud storage - outsourcing and offloading storage
* File-backed file system - Store an entire filesystem in a large file
* Filesystem encryption, Linux Unified Key Setup (LUKS)

!! Network file system (NFS)

Sun Microsystems, 1984 for diskless clients

Client / Server model
Exports list (shared directories) on NFS server
* Contains directory, who can access it, and their permissions
File locking
root access 
quota management

!! NFS Versions:  

** Stateless (over UDP)
*** Lightweight and faster at the expense of reliability
** 64-bit file sizes (files larger than 2gb)
** Still stateless (UDP) by default
** TCP option
** Performance improvements
** Required auxiliary protocols to manage filesystem exporting (mountd), server status (statd), and file locking (lockd).
*** All coordinated by RPC & the portmapper - {{Command{rpcinfo -p}}}
*** Portmapper:
** Additional performance improvements
** Stateful - TCP only, runs on port 2049
*** Eliminates need for those auxiliary protocols
*** Traverses firewalls and NAT 
*** Easy to setup firewall option
** Improved security
** Mandates security and ACL
*** Kerberos support

!! Configuration

Be sure to disable SE Linux !

Server configuration:  /etc/exports
* see exports man page for options
* /home  *(rw,root_squash)
** what_to_share  who_to_share_with(options)
** root_squash (default) vs. no_root_squash

nfs options (client side)
* see mount and nfs man pages
* nosuid for home directories
* noauto to not mount on boot (/opt/backups filesystem)
Use the mount command to show what is mounted and settings used to mount it
Display available NFS mounts:  showmount -e //hostname//

User id mapping:
* NFS clients map unknown users to nobody
* Big differences between NFS v3 and v4
** NFS v4 requires a separate service to properly map ~NFSv4 names (user@domain string) to local UID & GID
** May need to set the domain in /etc/idmapd.conf if DNS is not fully configured (forward and reverse)
* To properly map user ids:
** revert to NFS v3, or  (-o nfsvers=3)
** or, start idmapd (with nfs service)
* This may be handy for clearing idmapd cache: nfsidmap -c
** This may be helpful while troubleshooting an initial setup

!!! Our storage server setup

Install dependencies:
*NFS Server: nfs-utils nfs4-acl-tools portmap
*NFS Clients: nfs-utils 
Configure exports file on NFS server:
* printf "/home\t\t10.103.36.%d/29(rw,sync,root_squash,secure)\n" $ip >> /etc/exports
* Replace $ip with the last octet of the first IP address of your range
Start services
*On server:
**chkconfig nfs on
**chkconfig rpcbind on
**service rpcbind start
**service nfs start
** run: exportfs -rv
*On Client
**chkconfig netfs on
**service netfs start

Attach clients:
* mount -t nfs4 files:/home /home
* Add to fstab:
** printf "files:/home\t\t/home\t\t\tnfs4\tsoft,intr,rsize=8192,wsize=8192,nosuid\t0 0\n" >> /etc/fstab
** Test fstab configuration:
*** It's important to ensure your fstab file is error free.  If it contains an error your system may not fully boot to a multiuser runlevel on next system start.
*** umount /home
*** mount /home

* On Server:
** {{Command{showmount -e}}}
** {{Command{nfsstat}}}
* On Client:
** {{Command{showmount  -e files}}}
** {{Command{mount}}}


fuse - filesystem in userspace.  Enables users to mount various file systems.  Otherwise mounting is restricted to the superuser.
* Userand commands:
** {{Command{fusermount}}} - mount a filesystem
** {{Command{fusermount -u}}} - unmount a filesystem
* encfs - encrypted virtual filesystem
** mkdir /tmp///mountpoint//
** mkdir ~/private
** encfs ~/private /tmp///mountpoint//
** unmount with : fusermount -u /tmp///mountpoint//
* archivemount - mounts an archive for access as a file system
** mkdir /tmp///mountpoint//
** archivemount //archive// //mountpoint//
** unmount with : fusermount -u /tmp///mountpoint//
* sshfs - filesystem client based on ssh
** sshfs //user@host:path// //mountpoint//
** sshfs -h for more options
* fuseiso - mount ISO filesystem images
** fuseiso //isoimagefile// //mountpoint//
* vdfuse - Mounts any virtual hard disk format understood by ~VirtualBox
* ~GmailFS - Provides a mountable filesystem which uses your Gmail account as its storage medium

!! Bind mounts

Remount a file or directory tree somewhere else.
Make a file available in two locations
Especially useful for chroot

mount -&dash;bind //current// //new//

mount -&dash;bind /tmp /var/tmp

Visible via the {{Command{mount}}} command

!! Cloud storage

Amazon simple storage service (s3), google, azure

dropbox / owncloud

cold storage
 - aws glacier
 - google nearline

!! File-backed filesystems

dd if=/dev/zero of=disk-image bs=1M count=10
mkfs.ext4 disk-image
mount -o loop=/dev/loop0 disk-image /mnt

!! Encrypted partitions

Why Encrypt?
* sensative files (financials, personal info, company property)
* portables (laptop, tablet, phone) to protect from loss
* hdd disposal due to age or defect

How to encrypt:
* Individual files (with gpg)
* Filesystem stacked 
** Example: EncFS
** Files are stored on a regular, unencrypted filesystem
** Files are visible but their contents are encrypted.
* Block level
** Examples:  Truecrypt, LUKS
** The encryption key is required to mount the filesystem and view file names and contents.
* Combine with other utilities:
** partition -> raid -> encryption -> filesystem

Linux Unified Key Setup (LUKS)
 - A standard means of encrypting partitions within linux
 - Portable - Windows and android


<<tiddler [[Lab 21 - NFS]]>>
<<tiddler [[Lab 22 - Monitoring disk usage with Nagios]]>>
<<tiddler [[Lab 23 - Filesystem Options]]>>
<<tiddler [[Lab 24 - hack1 break-in]]>>

!! Reading

We will be discussing securing communication with ~OpenSSL next week and configuring services to utilize SSL certificates.  

Read up on generating SSL certificates:
* ~SysAdmin text book, section 23.4 starting on page 971  (Stop at configuring apache.  We will do this in class)
* If you haven't taken a crypto class, some SSL background info.  Our textbook does not cover SSL very well.
** The short version:
** Details:

! Material

!! Encryption Goals:
* Confidentiality - Prevent disclosure to unauthorized parties
* Integrity - Prevent tampering of transmitted data
* Authenticity - Ensure communication is genuine and with the intended target

!! Encryption basics

!!! Symmetric cryptography:
* Same key is used for both encryption and decryption of the message
* Also know as a shared secret
** {{Command{openssl aes-256-cbc -a -salt -in secretfile.txt}}}
* Pros:
** Fast
** Not resource intensive 
** Useful for small and large messages
* Cons:

!!! Asymmetric:
* Public key cryptography
* Two keys instead of one shared secret
** public key - available for everyone.  Can be published
** private key - kept secret and secure.  Typically locked with a passphrase.
* Data encrypted with one key can be viewed or verified by the other
** Can be used for encrypting
** And ...
* Cons:
** Slow
** More resource intensive
** Only useful for small messages

!!! Symmetric / Asymmetric Hybrid
* Use asymmetric encryption only to transmit a symmetric key.
* Then use symmetric encryption for the actual message.
* Can safely exchange key data
* Fast
* Not resource intensive
* Useful for small and large messages

!! Encryption Uses:

* Encrypt or sign files and messages
* user keys for authentication
** Use ssh-keygen to generate keys
* host keys for encrypting communication between client and server
* DS Record - chaining trust
** We need to start from a hardcoded point of trust.  
*** root keys ship with bind:  {{File{/etc/named.root.key}}}
*** Update from website:
*** Download the root key:  {{Command{dig . dnskey > /tmp/root.key}}}
** DNSSEC trace tree from root: {{Command{drill -k /tmp/root.key -TD //username// SOA}}}
** Chase DNSSEC signatures: {{Command{drill -S  -k /tmp/root.key www.//username//}}}
** [[Verisign DNSSEC debugger|]]
* Key rotation
** ZSK: Quarterly
** KSK: Annually
* RR Hash expiration
** {{Command{dig soa +dnssec}}}

!!! SSL Certificates
* A SSL certificate contains information about the owner and their public key
* Signed by a Certificate Authority (CA) to establish trust
** A company like Godaddy, Verisign, or Entrust
** Free CA: or [[StartSSL|]]
** Nonprofit CA to issue free certs:
** Self-signed certificate
* CA signature added to the certificate
* Certificate Verification via host name
** Host name in the URL must match the host name in the certificate (single host)
** Or use a wildcard certificate for many sites (*
** ~CAs are //supposed// to verify ownership / control of that host or domain

!!!! SSL Trust

CA certificate stores
* Hardcoded list of trusted root CA certificates in either the application or operating system
* Stored within {{File{/etc/pki/tls/certs/ca-bundle.crt}}} in ~CentOS
* {{Command{grep Issuer /etc/pki/tls/certs/ca-bundle.crt | less}}}
* Intermediate CA resellers
* Transitive trust
* Web of trust instead of a direct chain
* Certificate Authority weaknesses
** Several Breaches at CA Intermediaries
*** ~DigiNotar (2011) - Issued a wildcard certificate for google.  About 500 other fake certificates were issued.
** Bad actors
*** Man in the middle proxies
*** Malware
** Certificate revocation problems
* Leaks or vulnerabilities (Heartbleed)

!!!! Countermeasures for the weaknesses in the trust system:
* Public key pinning
** Lock a certificate to a specific CA

* ~DNS-based Authentication of Named Entities  (DANE)
** Remove the ~CAs from the process
** Use DNS to authenticate certificates much like SSH fingerprint records
** Add a tlsa resource record to your DNS
** Move from web of trust to chain of trust like DNSSEC
** Since DNS is totally open, if something is compromised it should be detectable
** Easy to revoke certificates
** [[DerbyCon Video|]]

!! Web Encryption

!!! Background

HTTP encapsulated with TLS
 - Transport Layer Security
 - Replacement for SSL protocol
Encryption layer on top of HTTP
Used to authenticate the server and secure communication

Use Hybrid encryption
* Encryption algorithms are decided by the browser and the server
* Most secure method available to both is used
* Symmetric encryption is used for the transaction
* But we need to safely share the key
** Asymmetric crypto is used to send the key
** Server public key is stored inside the site's certificate

HTTPS Handshake:
* Browser initiates the connection
* Server responds with its certificate 
* Browser advertises its encryption methods and sends a symmetric session key encrypted with the server's public key
* Server decides which cipher to use
* Server and client use this session key for symmetric encryption of the data

Public key crypto is only used to establish faster symmetric encryption

!!! Implementation

!!!! Key generation
* Save within www:/opt/work/certs/
* Be sure set file permissions appropriately
* SSL Keys
** Securing keys with passphrases
** Create: {{Command{openssl genrsa -des3 -out www.//username//.key 2048}}}
** Verify: {{Command{openssl rsa -noout -text -in www.//username//.key}}}
* Certificate Signing Request (CSR)
** Create: {{Command{openssl req -new -key www.//username//.key -out www.//username//.csr}}}
** Verify: {{Command{openssl req -noout -text -in www.//username//.csr}}}
* Certificate Authority (CA)
** I'll play this role.  These are the commands I'll execute as the CA:
** Create CA Key: {{Command{openssl genrsa -des3 -out cs407CA.key 2048}}}
** Create CA Cert: {{Command{openssl req -x509 -new -nodes -key cs407CA.key -out cs407CA.crt -days 1825}}}
** Sign a certificate:  {{Command{openssl x509 -req -in www.merantn.csr -CA cs407CA.crt -~CAkey cs407CA.key -~CAcreateserial -out www.merantn.crt -days 735}}}
** Display: {{Command{openssl x509 -noout -text -in cs407CA.crt}}}

View server certificate:  {{Command{openssl s_client -connect //hostname//://port// -showcerts}}}
* Test server SSL quality:

!! Additional Reading
SSL/TLS Details:

! Assignment

<<tiddler [[Lab 25 - SSL Certificates]]>>
<<tiddler [[Lab 26 - Install OpenLDAP]]>>

!! Reading

~SysAdmin Section 19.3 (Pg 728) - LDAP
! Old Business

!! Project progress reports
 - {{File{~/cs407/project/cs407-//username//-progress1.pdf}}}

!! admin SSH keys

Be sure I can access your ~VMs via the admin account.  Add my public key:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjDXBhIjaHcNNsNXkWxHmuwnU1+q0mMXSdobP+DP/X/57j9Txne6akT1nN8uF5YrTpRN/pIlKhsPFHVHjdPRzllV4vSBNyU8HWQmhPYjAvMsKGURU7PcQG40gkSe8hWCMRjGt37yj25c9mvb1A9hsC42jGIK5VlzoJPN/e8JRm7vXA7GFfrrutsYItnU3T1AG+B4tv/OyUE+xHkDcrdGPjn8M76mxgkBH1f/CyhOAC0D+ldQ5KXpgBm7P8oKhVDAXXJhoWMmpMjWiYRGVHEIJrnptBK9SznSvwN82K3H3jITuGlbtZOek9MBXPY5hRPb7PC6j6w5npF0Q/ZiEOmnIb merantn@cs407-2

!! ~OpenSSL continued

!!! Recent news:

!!! Verify directory cert

{{Command{openssl req -noout -text -in directory.//username//.csr}}}

!!! Abusing the Certificate Authority Trust model

CA trust in the browser

CA trust by the system:
{{Command{openssl s_client -connect -showcerts}}}
{{Command{openssl s_client -connect www.//username// -showcerts}}}

Add our class CA certificate to the trusted cert store for our systems.
* [[CS 407 CA Certificate|]]
* {{Command{cat cs407CA.crt | openssl x509 -text -noout >> /etc/pki/tls/certs/ca-bundle.crt}}}
* {{Command{cat cs407CA.crt >> /etc/pki/tls/certs/ca-bundle.crt}}}

If anyone has access to your system or application certificate store, they can abuse that access to add their own certs
Protect your private keys and your CA certificate store!

! New Material

!!Central Authentication

* Security vs. convenience

Possible Services for centralized authentication:
* NIS - Network Information System
* LDAP - Lightweight Directory Access Protocol
* Active Directory (built on LDAP)

* A protocol for communication between the client and server
* Modular components:
** Front end receives a request, decodes it, and passes it to the back end for processing
** Back end completes request and returns results to front end to be sent to the client
*** Back end stores the data
*** It is typically a database (Berkeley DB), but many other backend types are allowed. 
** Optional overlay - Sits between front end and back end to trigger other actions on data passed through
* tree-like data hierarchy 
* Schemas describe the contents of the sub-trees and define attributes (name, data types, descriptions)
** Schema also defines whether an attribute is optional or required, may only exist once per record or may be duplicated
* Data entries consist of a set of attributes 
* Attributes are name/value pairs

Tree hierarchy:
* dc = domain component
* ou = organizational unit
* cn = common name
* dn = distinguished name

LDAP Operations:
* Bind - Connect and authenticate
** Connections may be anonymous or authenticated
* Search - Search the database and read entries
* Add - Insert entries
* Delete - Remove entries
* Modify - Alter entries
* ~StartTLS - Request encryption

* Standard Bind (port 389): ldap:&#047;/host:port/baseDN?attributes?scope?filter
* Secure Bind (port 636): ldaps:&#047;/host:port/baseDN?attributes?scope?filter
* Base DN = Where in the tree to start the search
* attributes = List of attributes to retrieve (comma separated)
* Scope = Define the search scope of base (default), one, or sub
** base - search only within the specified base
** one - search only one level below the base
** sub - search the entire sub-tree below the base
* filter = LDAP search filter.  Defined in [[RFC 4515|]]

Data is typically displayed in the LDAP Data Interchange Format (LDIF) 

!!! LDAP Searching:
Anonymous Bind:
ldapsearch -Z -h directory 
ldapsearch -Z -h directory '(uid=*)' uid loginShell

Authenticated Bind
ldapsearch -Z -h directory -D cn=root,dc=cs,dc=sunyit,dc=edu -W '(uid=*)' uid shadowLastChange

!! LDAP Configuration:

LDAP configuration may be stored in a flat file (slapd.conf)
Or, within the LDAP tree 

Install ~OpenLDAP.  See [[Lab 27 - OpenLDAP Server]]

Create the symlink:  ln -s openldap-2.4.40 openldap
Create ldap service account and group, uid: 389, gid: 389

cd /opt/work/openldap/etc/openldap

back up slapd.conf
- cp -p slapd.conf slapd.conf.orig

edit slapd.conf
*remove the version string throughout the file:  -2.4.40
** This will make the configuration portable between versions.
* Add additional schemas:
** include         /opt/work/openldap/etc/openldap/schema/cosine.schema
** include         /opt/work/openldap/etc/openldap/schema/inetorgperson.schema
** include         /opt/work/openldap/etc/openldap/schema/nis.schema
* Set suffix
 *Set rootdn
 *Set rootpw

Secure the slapd config file and set ownership
 - This file contains our hardcoded root credentials and must not be readable by anyone but root

Set proper permissions on the data directory 
 - it must be owned by the ldap service account so changes can be saved

client tools vs. server tools
* Client tools:  ldap*
* server tools:  slap*
* Don't use the server tools to read or manipulate the data while LDAP is online

Some stuff to get us started:

Make sure selinux is disabled:
{{Command{setenforce 0}}}
{{Command{sed -i -e '/^SELINUX=/s/enforcing/disabled/'  /etc/selinux/config}}}

As well as the firewall:
{{Command{service iptables stop}}}
{{Command{chkconfig iptables off}}}

* slapd startup script:  {{Command{wget -O /etc/init.d/slapd}}}
* a config file for the startup script:  {{Command{wget -O /etc/sysconfig/ldap}}}
* {{Command{chmod +x /etc/init.d/slapd}}}

* Add slapd script for chkconfig management
** {{Command{chkconfig &#045;-add slapd}}}

* Start slapd on boot and start immediately:

{{Command{ldapsearch -x -b dc=merantn,dc=cs407,dc=net}}}

!!! Build the LDAP directory tree and add user data

''Be sure to change my username to yours in the command strings and downloaded files!''

{{Command{cd /tmp}}}

The core of our LDAP tree:
* {{Command{wget -O /tmp/initial.ldif}}}
* {{Command{ldapadd -D cn=root,dc=merantn,dc=cs407,dc=net -W -f initial.ldif}}}

A template user record.  We'll add a user account for me and then change the information to add one for you.
* {{Command{wget -O /tmp/user.ldif}}}
* {{Command{ldapadd -D cn=root,dc=merantn,dc=cs407,dc=net -W -f user.ldif}}}

Change this user.ldif file from my info to yours.  Be sure to use your CS uid and gid values
* {{Command{ldapadd -D cn=root,dc=merantn,dc=cs407,dc=net -W -f user.ldif}}}

* {{Command{ldapsearch -x -b dc=merantn,dc=cs407,dc=net}}}

Secure the directory data with an ACL:
access to attrs=userPassword
        by anonymous auth
        by self write
        by * none
access to attrs=mail,gecos,displayName,loginShell
        by self write
	by * read
access to *
        by * read

{{Command{ldapsearch -x -b dc=merantn,dc=cs407,dc=net}}}

We need to encrypt our communication, especially for authenticated binds:
TLSCertificateFile      /opt/work/certs/directory.merantn.crt
TLSCertificateKeyFile   /opt/work/certs/directory.merantn.key
TLSVerifyClient 	never

{{Command{openssl s_client -connect localhost:636 -showcerts }}}

If the certificate is not trusted, you may need to add our fake CA cert to your local certificate store:
wget -O /etc/pki/tls/certs/cs407CA.crt
openssl x509 -text -noout -in /etc/pki/tls/certs/cs407CA.crt >> /etc/pki/tls/certs/ca-bundle.crt
cat /etc/pki/tls/certs/cs407CA.crt  >> /etc/pki/tls/certs/ca-bundle.crt

openssl s_client -connect localhost:636 -showcerts 

We will continue with client configuration next class.

! Assignment

<<tiddler [[Lab 27 - OpenLDAP Server]]>>
! Old Business


Complete server configuration from Monday.

! Material

!! Complete server configuration

!!! Expand database indexes 

index   cn,sn,uid 	pres,eq,approx,sub
index   member          eq

rebuild with {{Command{./slapindex -f ../etc/openldap/slapd.conf}}}

!!! Verify SSL

{{Command{openssl s_client -connect directory.''username'' -showcerts}}}

In case we need to add the CA certs:
wget -O /etc/pki/tls/certs/cs407CA.crt
openssl x509 -text -noout -in /etc/pki/tls/certs/cs407CA.crt >> /etc/pki/tls/certs/ca-bundle.crt
cat /etc/pki/tls/certs/cs407CA.crt  >> /etc/pki/tls/certs/ca-bundle.crt

{{Command{ldapsearch -Z x -b dc=''username'',dc=cs407,dc=net}}}
The -Z will request ~StartTLS

Will will likely run into a certificate problem here.  Better logging will help us identify and correct it

!!! Enable logging

Enabling logging will help troubleshoot enabling SSL support.  To enable ~OpenLDAP logging:

Edit your slapd.conf file:  Add this line near the top after the include lines
loglevel	256

If you're interested in learning more, the slapd.conf man page can be viewed by running:
{{Command{man -M /opt/work/openldap/share/man slapd.conf}}}

The ~OpenLDAP service will send its logs to syslog using the local4 facility.  Edit the /etc/rsyslog.conf file to instruct syslog to save the log data to a file.
You should see a line that begins with local7 near the end of the file.  Duplicate that line and modify so that you now have:

{{Command{vi /etc/rsyslog.conf}}}
# Save slapd server logs
local4.*                                                /var/log/slapd.log

Restart rsyslog and slapd so your changes take effect:
{{Command{service rsyslog restart}}}
{{Command{service slapd restart}}}

Tail the slapd.log file to view new entries.  Either open a new window or use your job control commands to monitor new lines as they arrive.

{{Command{tail -f /var/log/slapd.log}}}

{{Command{ldapsearch -Z -x -b dc=''username'',dc=cs407,dc=net}}}

!! Configure client systems

!!! Making your system aware of LDAP users:

Required client packages:
{{Command{yum install sssd openldap-clients}}}

!!!! Configure openldap client:
set search base when performing an ldapsearch against another site
 - {{Command{ldapsearch -x -h -b dc=merantn,dc=cs407,dc=net}}}
 - ldap.conf sets defaults for your site so they don't have to be specified on the command line

{{Command{wget -O /etc/openldap/ldap.conf}}}
Change this config file to match your environment (change my username to yours)

{{Command{ldapsearch -x -Z}}}

!!!! Configure System Security Services Daemon (sssd)
* {{Command{wget -O /etc/sssd/sssd.conf}}}
* Set sssd to start on boot
* Start the sssd service immediately
* You may need to fix a permission problem preventing it from starting.  Check the logs.

!!!! Configure name-service switch - nsswitch.conf
* We can communicate with the LDAP service and display user information, but those users are not yet known to the system
* nsswitch controls how a process queries for various database items, like hosts, users, and groups
* This is called from library routines, not a service.  The configuration file takes effect immediately.
* We need to instruct this facility to also look elsewhere for user information
* Add the ''sss'' keyword to the end of the lines for passwd, shadow, and group.
* Verify:  {{Command{id ''username''}}}

!!!! Configure PAM
* Back up your sssd.conf file.  authconfig may mangle it.
** {{Command{cd /etc/sssd/}}}
** {{Command{cp -p sssd.conf sssd.conf.bak}}}
* {{Command{authconfig &#045;-enablesssd &#045;-enablesssdauth &#045;-enablelocauthorize &#045;-update}}}
* Check your sssd.conf file
** {{Command{diff sssd.conf sssd.conf.bak}}}
* Restore if necessary
* Restart sssd
* Verify:  {{Command{ssh ''username''@localhost}}}

!!!! Enable getent enumeration
* {{Command{getent}}} - Get entries from an administrative database
* {{Command{getent passwd}}} - Display password map
* Add to domain section of {{File{sssd.conf}}}:  ''enumerate=true''

* Password field:
** * = locked, 
** x = see shadow for password
* The sssd passwd field is hardcoded to a *.  Change it to x in sssd.conf
* Add to nss section of {{File{sssd.conf}}}:  ''pwfield=x''

!!!! Credential caching

Cache credentials for x days if authentication provider is offline.

Add to the domain section:
* cache_credentials = True
* offline_credentials_expiration = 1   

!!! ldapvi

Install ldapvi via the epel repo

ldapsearch -x -b dc=''username'',dc=cs407,dc=net

ldapvi -h directory -D cn=root,dc=''username'',dc=cs407,dc=net &dash;-discover

!!! shelldap

* From package:  yum install perl-~YAML-Syck perl-~Term-Shell perl-~TermReadKey perl-~Algorithm-Diff perl-CPAN
* Via CPAN:  cpan Net::LDAP
** Go with all defaults when prompted

! Assignment

<<tiddler [[Lab 28 - OpenLDAP Clients]]>>

!! Reading

~SysAdmin Chapter 9 - Periodic Processes
~SysAdmin Chapter 10 - Backups (Stop at 10.7 on page 317)

!!Scheduled tasks

* cron - run periodically
* at - run once at a scheduled date & time

!!! Use Examples:
* Log rotation
* Daily reports
* Garbage collection
* Vulnerability checks
* System updates
* Source code updates
* mysqldump - database backups
** create a read-only mySQL account
** save backup to /opt/work/backups
* DNSSEC key rotation
* DNSSEC zone resigning
* System backups

* Scheduling a one-time job for a more convenient time
** ie: something that may be bandwidth or CPU intensive.

!!!cron - run periodically
** A service that is installed with the OS and running by default
** Started on system boot 
** Permission granted via {{File{/etc/cron.{deny,allow&#125;}}} files
* System cron configuration:
** {{File{/etc/crontab}}} file
** {{File{/etc/cron.*}}} directories
* User cron configuration: 
** {{Command{crontab}}} command for scheduled user jobs
** {{Command{crontab}}} [-e|-l]
** User cron config files are stored in {{File{/var/spool/cron/}}}

!!!Crontab file format
*See {{File{/etc/crontab}}}
* Declare variables
* Output optionally sent to the owner (on by default)
* Command execution fields:
** Time to execute command, (minute, hour, day, month, weekday) 
** User to run as (when running from system crontab)
** Command string to execute
* Special time nicknames:
** @reboot
** @daily
** Complete list in man page
* Special time formatting:
** */2 : Every 2 hours, months, days, etc
** 1-4 : From 1 to 4
** 1-6/2 : Every other between 1 and 6 
** 2,5 : 2 and 5

!!! Cron man pages:
* Check man page for the cron command
* Notice the ''See Also'' section at the bottom where crontab is listed in two different manual sections
* {{Command{man man}}}

!!!at - run once
* System dependent:
** ~FreeBSD - The atrun utility is executed via cron every 5 minutes to check for and run {{Command{at}}} scheduled tasks
** ~CentOS - atd - Daemon running in the background for processing tasks scheduled tasks via the {{Command{at}}} utility
** Not installed or running by default (on ~CentOS)
** Must be set to start on boot and be manually started after installation.
*{{Command{at}}} user command with time for task to execute specified as an argument
** flexible time formatting
*** at +15 minutes
*** at 4:15
*** at 4pm tomorrow
*** at 4pm October 15
* Display scheduled job with {{Command{at -c}}}
** Scheduled jobs stored in /var/spool/at files
** atq - display scheduled at jobs
** atrm - remove scheduled at job
** Can use {{File{/etc/at.{allow,deny&#125;}}} files to control access

!! Backups

Traditional backup mediums
* Tapes
* Optical (cd/dvd)
* Disk 

Backup strategies
* What to back up
* Interval (how often)
* When to run (day/time)
* Full or incremental
** Full - All files
** Incremental - Files which have changed
* Destination: Onsite or offsite
* Security: Physical & electronic
* Testing

Standard UNIX Tools:
* tar
* rsync
* dump/restore
* rsnapshot

LVM Filesystem Snapshots:
* sync - flush filesystem buffers first
* Snapshot - record a filesystem at a point in time
** {{Command{lvcreate -s -L //size// -n testsnapshot /dev/Storage/work}}}
*** size can be fixed or variable.  See man page.  ( -l 50%FREE )
** Backups - use for backing up data
*** run dump against the snapshot device then delete it
** Testing: Use for tests & debugging.  Discard snapshot after use.
*** Mount the snapshot as the original mountpoint and merge/destroy when finished
*** Merge with: {{Command{lvconvert &dash;-merge //snapshot//}}}

Snapshot demo on the www VM:
Check the amount of free space in the volume group.  Note the ~VFree value for the Storage VG

Create a snapshot of the work logical volume
{{Command{lvcreate &#045;-size 100M &#045;-snapshot &#045;-name src_snap_oct22 /dev/Storage/src}}}

Check the amount of free space after snapshot creation.  Note the VFree value for the Storage VG

Display logical volume information.  Note the Data% value for the snapshot.  If this reaches 100% the snapshot will be destroyed. 
Only changes will be written to the snapshot.

Display logical volume information, including snapshots associated with a LV
{{Command{lvdisplay /dev/Storage/src}}}

Display additional snapshot information:
{{Command{lvdisplay /dev/Storage/src_snap_oct22}}}

Unmount the original /opt/src volume:
{{Command{umount /opt/src}}}

Mount the snapshot in its place:
{{Command{mount /dev/Storage/src_snap_oct22 /opt/src}}}

Just because space is shown as available, doesn't mean it really is.  We're still limited by the size of the snapshot logical volume

Create some data:
{{Command{dd if=/dev/zero of=/opt/src/zeros bs=10M count=3}}}
{{Command{ls -l /opt/src/}}}

Maybe we should make this snapshot a little larger:
{{Command{lvextend &#045;-size 200M /dev/Storage/src_snap_oct22}}}

Unmount the snapshot:
{{Command{umount /opt/src}}}

Mount the original /opt/src volume (via fstab):
{{Command{mount /opt/src}}}

Note the absence of our zeros file:
{{Command{ls -l /opt/src/}}}

Lets merge in our changes:

First unmount the volume
{{Command{umount /opt/src}}}

The merge in the changes:
{{Command{lvconvert &$045;-merge /dev/Storage/src_snap_oct22}}}

If we didn't want to merge changes, instead delete the snapshot:
{{Command{lvremove /dev/Storage/src_snap_oct22}}}

System backups with dump
* sync
* Back up filesystems with {{Command{dump}}}
** Track backups with -u option
*** Saved to /etc/dumpdates
*** Access backup history with {{Command{dump -[wW]}}}
** Backup levels: full or incremental
*** full (level 0) : All files
*** incremental (levels 1 to 9) : Files changed since last level of a lesser or equal value
** Compression?  gzip or bzip2 available.
** Mark files to skip with nodump flags
*** Display a file's flags:  {{Command{lsattr /opt/src/zeros}}}
*** Add the nodump flag:  {{Command{chattr +d /opt/src/zeros}}}
* Restore files with {{Command{restore}}}
** -x : extract specified files (or all)
** -r : rebuild filesystem (for incremental chaining)
** -i : interactive restore

Can also combine with pgp / gpg to encrypt the backup files.

A couple other backup tools worth mentioning
* tar
* dd - block level duplication of a device
* clonezilla
* bacula - Cross platform full backup solution
* ntfsclone - Capture a NTFS filesystem
* cloud services
** amazon cloud - (S3 or glacier storage)
** tarsnap - secure backups
** crashplan - Cross platform carbonite clone


<<tiddler [[Lab 29 - Backups & Cron]]>>
<<tiddler [[Lab 30 - DNSSEC Signing]]>>

!! Reading:

* ~SysAdmin Chapter 21, stop at section 21.8
* ~SysAdmin Chapter 22, section 22.8
** Experiment with the netstat and nmap tools to discover open ports on local and remote systems
! Material

System enumeration - Scan and inventory information about the system

Motivation / Goals:
Administrator - see what your system is up to
 - Learn more about the system
 - troubleshoot performance problems
 - ensure OS & software is up to date
 - enhance security
 - Identify weaknesses and determine points of entry

* users and account details
* services
* software
* OS & software versions
* configuration

!! System

Inventory OS and server software on the system, including versions.
Inventory storage areas and users
Check configurations

!!! Kernel, OS, and hardware:
* uname -a
* cat /proc/version
* cat /etc/*-release
* cat /proc/cpuinfo
* cat /etc/proc/meminfo
* free
* df
* dmesg
* lspci
* cron
* Process info:
** top
** ps

!!! Software:

* List all installed packages:  rpm -qa
* Display active repos: yum repolist
* List all installed packages: yum list installed
* Display packages with available updates: yum check-update
** Yum security plugin:
** yum -y install yum-plugin-security
*** man yum-security
*** Display a summary of outstanding security notices: yum updateinfo summary
*** Display available security-related updates: yum &#045;-security check-update
*** List outstanding advisories: yum updateinfo list security
*** Display additional info on an advisory:  yum updateinfo info //advisory//
*** Update packages with outstanding security notices:  yum &#045;-security update
** Query specific software
** mysql &#045;-version
** perl -v

!!! User information:
* cat /etc/passwd
* cat /etc/group
* cat /etc/nsswitch
* w
* id
* last 
* lastlog
* lastcomm (accounting)
* sudo:  
** /etc/sudoers 
** sudo -l

!!! The environment:
* set
* env
* history
* cat ~/.bash_history
* ls -la ~/.ssh/

!!! Filesystem:
* Find set-uid files: find / -perm -4000 -type f
* Find world-writable files:  find / -perm -2  ! -type l ! -path "/proc/*"
* List open files: lsof 

!!! Network
* host name
* dns info
* Interface info:  ifconfig -a
* Routing: netstat -r
* Network neighbors:  arp -a
* Firewall: iptables -L
* Listening ports and existing connections:
** netstat -tunap
** lsof -i -n
* Required network ports
* port scanning
** Identify open ports
** banner grabs

fuser - Identify process using a file or socket
 - fuser 22/tcp
 - nc example

lsof - List open files
 - lsof -i:22

nmap - port scanner -
*Check version!
*Identify open ports.  Maybe try to communicate with them?
** nmap
** nmap -p 22
** nmap version scanning
*Or fingerprint the system
** nmap -O -v
** nmap -A -T4 

Scan binaries with the strings command

!!! System Profiling:

!!!! External View:
[[OpenVAS|]] - Open Source vulnerability scanner and manager

!!!! Internal View:
[[SCAP|]] - Security Content Automation Protocol
 - [[Data Repository|]]
 - [[OpenSCAP|]]
 - [[CentOS 6 data file|]]
[[tiger|]] - Unix security audit and intrusion detection tool

!!! Integrity verification

rpm -Va
       S file Size differs
       M Mode differs (includes permissions and file type)
       5 digest (formerly ~MD5 sum) differs
       D Device major/minor number mismatch
       L readLink(2) path mismatch
       U User ownership differs
       G Group ownership differs
       T mTime differs
       P caPabilities differ

       c %config configuration file.
       d %doc documentation file.
       g %ghost file (i.e. the file contents are not included in the package payload).
       l %license license file.
       r %readme readme file.

yum verify plugin
- yum install yum-plugin-verify

verify a single package: yum verify ls
verify everything: yum verify-all
skip config files: &#045;-verify-configuration-files=yes|no

Tripwire -
-  tripwire -m u -a -r /var/db/tripwire/report/filename

! Assignment

<<tiddler [[Lab 31 - Network enumeration]]>>

!! Reading

Read ~SysAdmin 22.11 & 22.12 (Firewalls)

!!Packet filter firewalls

Another component to system security
* Filter unwanted network traffic
* Log & monitor network traffic
* Block brute force attacks
* Rate limiting for minor ~DoS events

Filter minimally based on source or destination address, ports, or protocol types
Default to deny or default to allow
Optional logging
 - logging useful for regular monitoring and debugging

Ingress or Egress filtering
 - Control what flows in and out of the system

!! Developing firewall rules
* We must first understand what communication is expected to take place
** Source and destination
*** Is it a new connection or related to an existing connection ?
** Match services to port numbers
*** Consult /etc/services
*** Low ports 1-1023 are privileged.  They may only be bound by a root-controlled process.
** Observe what is currently listening for connections:
*** netstat -tunap
*** lsof -i -n -P 
* Create rules to allow desirable traffic
* Determine if any traffic should be blocked
* Decide what to do with remaining 
** Allow but log, or
** Deny

!!Stateful inspection - State module

- Stateless - inspect each packet in isolation.  Examine source and destination hosts and ports then decide what to do.
- Stateful - maintain the state of network connections.  These states can be used to determine policy.

Inspect the traffic to allow expected replies
* -m state &nbsp; &#45;-state //state//
* State is a comma delimited list of:
** NEW - the packet has started a new connection
** ESTABLISHED - the packet is associated with a connection which has seen packets in both directions
** RELATED - the packet is starting a new connection, but is associated with an existing connection
** INVALID - the packet  could not be identified for some reason (typically some type of error)

TCP - already stateful:
* 3-way handshake
* Evaluate TCP flags to determine state

UDP - stateless
* no flags to evaluate
* kernel tracks outbound UDP packets.  Responses to outstanding requests are marked

!!Linux [[netfilter|]]
* controlled by iptables command

!!! Table:
* Sets of chains 
* Default table is named filter
* Additional tables:
** NAT table
** Mangle table - for specialized packet alteration (~QoS)
** Raw table - for configuration exemptions

!!! Chains of rules:
* Firewall rules are grouped into chains
* Rules within a chain are interpreted in order, top to bottom
** Until a match is found
** Or the default target is reached (ACCEPT or REJECT)
* Default chains:
** INPUT: traffic addressed to the system
** OUTPUT: traffic leaving the system
** FORWARD: all packets arriving on one network interface and leaving another
* Custom chains can be created for organizing similar rules

!!! Rules:
* Rules contain a criteria and a target
* The criteria is based on attributes of the packet, such as IP addresses or ports.
* If the criteria is match, either perform the specified action or continue rule processing within the target
* If the criteria is not matached, move on to the next rule.
* Terminate with the chain's default target

!!! Targets:
Each rule contains a target clause to determine what to do with matched packets:
* ACCEPT - allow the packet to proceed
* DROP - silently reject the packet (causes TCP retries)
* REJECT - reject the packet with an ICMP error message
* LOG - track the packet as it matches a rule
* REDIRECT - redirect packets towards a proxy
* RETURN - terminate user-defined chains
* QUEUE - transfer packets to local user programs via a kernel module
* A custom chain may be specified as a target.  Rules in that chain will be evaluated.

!!! iptables Commands

iptables -h

!!!! Saving your rules
iptables-save > /tmp/iptables.rules
iptables-restore < /tmp/iptables.rules

service iptables save
rules are stored in /etc/sysconfig/iptables

!!!! Firewall Operations:
| !Option | !Definition |
|-L [&#45;-line-numbers] [-v] |List all rules|
|-I //chain-name// //position-number//  //rule// |Insert rule into a chain|
|-A //chain-name//  -i //interface//  -j  //target// |Append the current target to the chain|
|-D //chain-name// //position-number// |Delete a rule from a chain|
|-P //chain-name//  //target// |Sets default policy for the chain|
|-F //chain-name// |Flush all rules in a chain|
|-N //chain-name// |Create a new chain|

!!!! Filter criteria command line options:
| !Option | !Definition |
| -p proto |Match by protocol: tcp, udp, or icmp|
| -s source-ip |Match host or network source IP address|
| -d dest-ip |Match host or network destination address|
| &#45;-sport port# |Match by source port|
| &#45;-dport port# |Match by destination port|
| &#45;-icmp-type type |Match by ICMP type code|
| -i int |Match by interface|
| &#33; |Negate a clause|
| -t table |Specify the table to which a command applies (default is filter)|
| -j //target// |Specify target to use|

!!!! Extensions:
| -m state &nbsp; &#45;-state //state// |filter based on specified //state//|
| -m multiport &#45;-dports //port1//,//port2//,...//portN// |filter multiple ports|
| -m owner &#45;-uid-owner //uid// |filter based on user name|

!! Examples:


iptables -L --line-numbers -v

# Allow established traffic:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -s -p tcp &#45;-dport 4444 -j ACCEPT
iptables -A INPUT -p tcp -m multiport &#45;-dports 20,21 -j ACCEPT

iptables -A OUTPUT -p tcp -m multiport &#45;-dports 20,21 -j REJECT

# SSH chain:
iptables -N SSH
iptables -A SSH -p tcp --dport 22 -j ACCEPT -s
iptables -A SSH -p tcp --dport 22 -j ACCEPT -s
iptables -A SSH -p tcp --dport 22 -j ACCEPT -s
iptables -A SSH -p tcp --dport 22 -j ACCEPT -s
iptables -A SSH -p tcp --dport 22 -j ACCEPT -s
iptables -A SSH -p tcp --dport 22 -j LOG -m limit --limit 1/sec --log-prefix "IPTables-SSH: " --log-level 4

iptables -I INPUT 6 -j SSH -m state --state NEW

! Assignment

<<tiddler [[Lab 32 - Host-based Firewalls]]>>

!! Reading:

~SysAdmin sections:

* 22.7 (Pg 913) Chroot
* 22.9 (Pg 922) MAC


! Material

!! Linux Basics

Many different distros
* Server (~CentOS, ~ClearOS)
* Desktop  (Fedora, Mint)
* Dual (Ubuntu, Debian)
* Source / minimal  (Gentoo)
* Special Purpose  (Kali, Clonezilla, ~GParted)

Obtaining a distro
* Distro website
* [[DistroWatch|]]

Verify ISO and burn

* Dual boot
* Virtualization
* Live DVD / USB

Our class ~VMs:
* OS already installed
* ~CentOS minimal
* Copied from VM template

!! Bringing our ~VMs Online

!!! Review ~DogNet network topology 

!!! Discuss basic networking

* The ~NetLabs subnet is, a class B private IP block.
* The portion of this network assigned to our class is
* Bit boundary - dividing point between bit values that are always the same (the network) and bit values that will vary (the hosts)
** The CIDR mask is derived from this
** Also used for determining the network and broadcast IP addresses

!!! Access test VM and set IP address.

!!!! Distribute IP addresses.  Each user has a block of ~IPs to work with.

* Start host assignment at .32:

| !Start IP | !Username |
| 32 |biscarm|
| 40 |brandtg|
| 48 |dennism4|
| 56 |gomezd1|
| 64 |hoganlt|
| 72 |hookz|
| 80 |hunga|
| 88 |knappjf|
| 96 |messenc|
| 104 |morgansm|
| 112 |muhada|
| 120 |newmann|
| 128 |reevess|
| 136 |spierd|
| 144 |taraskr|
| 152 |zaydons|

* The default gateway for these systems, the next hop towards to campus network, is
* Our DNS resolver is

!!!! Manually apply static IP address immediately:

Direct your web browser to to work with your VM

* Access a root prompt
* Set the ip address
** {{Command{ifconfig eth0 inet 10.103.36.''x'' netmask}}}
** Test it:  {{Command{ping}}}
** But we can't yet leave our local network:  {{Command{ping}}}
* Set the default route
** {{Command{route add default gw}}}
** Test it:  {{Command{ping}}}
* Set the system host name:
** {{Command{hostname test}}}
* Test by reinvoking the shell

!!!! Test connectivity by accessing your VM via the network

* Open a terminal window on your lab system  (~Alt-F2 then type {{Command{xterm}}})
* Connect to your VM via SSH:  {{Command{ssh 10.103.36.''x'' -l root}}}
** Use the root password we set last week

!!!! Modify networking configuration files:

 - If you're not familiar with the vi editor, start getting used to it.  Check out {{Command{vimtutor}}}

The ifconfig and route commands we just used will cause these changes to take effect only for the current boot instance of the system.  These settings will be lost once the system reboots.  We need to edit the appropriate configuration files so these settings will be applied on system startup.

!!!! Edit the file /etc/sysconfig/network-scripts/ifcfg-eth0
# Change the ''ONBOOT'' option from ''no'' to ''yes''
# Change the ''BOOTPROTO'' option from ''dhcp'' to ''static''
# Ensure the HWADDR is commented out.
# Add the following lines:
Replace ''x'' with the IP address assigned to your VM

!!!! Edit the file /etc/sysconfig/network
# Change the ''HOSTNAME'' option to ''test''
# The name ''test'' is for this VM only.  A different host name will be used for future ~VMs.
# Add the line:

Add a line to /etc/hosts which resembles the following:
Replace the last octet of the IP address with yours and replace my username with yours.

{{{ test

!!!! Restart networking services
This command will restart networking services on your system, activating the new settings.  

{{Command{/etc/init.d/network restart}}}

!!!! Check your settings
Verify your configuration with the {{Command{ifconfig}}} and {{Command{route}}} commands.  

The output of {{Command{ifconfig eth0}}} should resemble:
[root@localhost ~]# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr FA:CE:99:23:0C:3D  
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::f8ce:99ff:fe23:c3d/64 Scope:Link
          RX packets:936 errors:0 dropped:0 overruns:0 frame:0
          TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:46636 (45.5 KiB)  TX bytes:5693 (5.5 KiB)
The last octet in the IP address above is unique to each system.  .24 is used here, your value should be different.

The output of {{Command{route -n}}} should resemble:
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface     U     1002   0        0 eth0     U     0      0        0 eth0         UG    0      0        0 eth0

Hostname verification should resemble:

[root@localhost ~]# hostname

[root@localhost ~]# hostname -f

The -f option requests the fully qualified domain name (FQDN).

!!!! Verify network connectivity
You should now be able to ping both the default gateway for our test network and fang by their IP addresses:
[root@localhost ~]# ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=1.45 ms
64 bytes from icmp_seq=2 ttl=64 time=1.23 ms
64 bytes from icmp_seq=3 ttl=64 time=1.23 ms
--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2399ms
rtt min/avg/max/mdev = 1.235/1.308/1.454/0.110 ms

[root@localhost ~]# ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=61 time=5.10 ms
64 bytes from icmp_seq=2 ttl=61 time=3.58 ms
64 bytes from icmp_seq=3 ttl=61 time=3.80 ms
--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2181ms
rtt min/avg/max/mdev = 3.580/4.163/5.106/0.676 ms

!!!! Configure DNS
Attempts to ping a system by its host name should fail.  DNS is not yet configured.
[root@localhost ~]# ping fang
ping: unknown host fang
[root@localhost ~]# ping
ping: unknown host

Add the following lines to /etc/resolv.conf

The first line will specify the DNS server to use for our mappings between hostname and IP address.  The second line will be appended to DNS queries that contain only a host name.  ie: ping fang

!!!! Remote connections with SSH

The configuration of the student test network will not allow direct outside connections to virtual machines.  You must first connect to a system on the CS network.
nick@trillian:~>ssh -l merantn
Last login: Sat Jan 24 18:16:57 2015 from
FreeBSD 10.1-STABLE (generic) #6: Mon Dec 15 15:50:34 EST 2014

Welcome to DogNET!

merantn@fang:~>ssh -l root
Warning: Permanently added '' (RSA) to the list of known hosts.
root@'s password: 
Last login: Thu Sep  5 19:52:42 2013 from
[root@localhost ~]# 

Note:  The ''-l'' above in the {{Command{ssh}}} command string is a dash followed by a lowercase letter ''l'', not the number ''1''.

!! Online lab Verification

Nagios checks (on campus only, for now)


!! Unix Review 

Continue from last class.

Review lab 1

!! File and Command summary

!!! Useful network commands

!!! Configuration files


<<tiddler [[Lab 02 - Bring VMs Online]]>>
!! Read Chapter 3
(Generally you can skip over Solaris and AIX parts)

!! Become familiar with your ~VMs
Make sure you can connect to them from home, both via SSH and console.

!Useful background info

Chapter 24 (983-997) - Virtualization
Chapter 14 - TCP/IP Networking
Chapter 15 - Routing
! Material

!!Unix Security

The only secure computer is one that's unplugged, locked in a safe, and buried 20 feet under the ground in a secret location... and I'm not even too sure about that one.
-Dennis Hughes, FBI

Began with Morris worm in the late 80s
Not much security until Morris worm showed what was capable
Started with a student wanting to map the internet
Exploited known vulnerabilities in sendmail and rsh
Allowed machines to be reinfected.  
No logic to prevent reinfection caused a ~DoS effect on reinfected systems.

Morris worm led to DARPA's creation of CERT (Computer Emergency Response Team) Coordination Center -
Coordination center for Internet Security incidents

!!! Unix Mentality
Open source - many eyes on the code for scrutiny
Large community - diverse experience and skill level
Full disclosure
- Window of vulnerability

Security is a balance with convenience and usability
* Increases in convenience many come with decreases in security
* Examples: 
** ldap for ssh key storage and sudo configuration
** ssh-agent & screen
** File sharing & replication:  NFS, dropbox, etc

!!! Vulnerability exploit cycle: 

Advanced attackers or researchers discover new vulnerabilities
Crude exploit methods or tools are distributed
Novice attackers use crude exploit tools
Automated scanning & exploit tools are developed
Automated scanning tools become widespread
New types of exploits are discovered

!!! Types of attackers:

Local users / insiders
Script kiddies / system vandals
Organized crime
Domestic Governments - [[NSA attacking SysAdmins|]]
Foreign Governments - [[Demo|img/cctv_hacking_screenshot.jpg]] [[Activity model|img/activitymodel1.gif]] [[translated|img/activitymodel2.jpg]]

!!! Motivation:

Personal Gain (Financial theft)
Trade / government secrets (Espionage)

Noisy vs. silent intrusion

!!! Where are the vulnerabilities:

Social engineering
* The human factor can be the weakest link in the chain
* People tend to want to be helpful

Shift from OS vulnerabilities to application vulnerabilities

Client issues:
* client software remaining unpatched (flash, java, browsers, Acrobat, MS Office)
** Email content scanning can keep malicious attachments out
** Malicious sites, flash and java applets can be mitigated with domain blacklists
* Application patching tends to be much slower then OS patching
* Vulnerable web sites

System issues:
* kernel exploits
* Denial of service
* privilege escallation 
* remote code execution
* Configuration errors
** Examples: 
** boot single user without a password
** Showing hashes in an LDAP anonymous bind
** Accessible configuration files or private keys
*** There's a reason sssd.conf and slapd.conf are locked down
*** Notes to other admins
* Weak Access controls
** Maintain strong root & user passwords
** Limit access to the system
** Limit access to particular areas of the system 
** Protect backups

Follow the principle of least privilege / least access
 - Keep everything as restrictive as you can

Increasing number of zero day vulnerabilities
- Bug bounties and exploits for sale

!!! Keep up to date!
 - Maintain latest versions or apply system / software patches 
Minimize exposure - remove unnecessary software and disable unused services

!!! Post exploitation - Maintaining system access
* Rootkits
** Software designed to hide processes, files or maintain access
* Malicious versions of system utilities
** Such as a hacked SSH to reveal credentials
* Remote access tools 
** A means for intruders to return
** Reverse shells
* Configuration changes
** ssh keys
** new users
* Key or password loggers

A compromised system can be used for:
 - Attacking other internal systems
 - Collection point for data exfiltration
 - Attacking other external systems

!!! Securing a new system:

Tools from [[Day 18]]

!!! Keeping informed

OS & Software mailing lists

Distro-specific lists

!!! Ongoing security evaluation

!!!! Basic system discovery & enumeration

Inventory OS and server software on the system, including versions.
Inventory storage areas and users
Check configurations

! Assignment

!! Shut down test ~VMs

The hackathon is this weekend.  We need to free resources on our Xen server to support it.

!! Project progress reports due Friday

<<tiddler [[Lab 33 - System enumeration and infiltration]]>>

!! Reading:

~SysAdmin sections:

* 22.7 (Pg 913) Chroot
* 22.9 (Pg 922) MAC
! Material

!! Agenda:

* Filesystem isolation with chroot
* Other mount types
* Domain sockets & Named pipes
* inodes

!! Filesystem isolation

chroot & jails
* chroot - confine a process to a specific directory
** chroot command
** chroot system call 
freebsd jails - shared kernel, separate OS

Important to enforce least privilege - make sure nothing can run as root.

!!! chroot example - Remote connections with SSH

Isolate remote users to a particular branch of the filesystem:

!!!! System changes:

Create chroot environment
Copy any needed binaries
Copy libraries
 - Identify which shared objects are needed with the ldd command
 - {{Command{ldd}}} : list dynamic object dependencies
Create devices:
*Need null and zero Pseudo-devices
*Pseudo-device - device files that don't map to real hardware
** Device types:
*** block - reads one block at a time (512 bytes)
*** character - reads on character at a time
** Device number:
*** major - identifies the driver associated with the file (type of device)
*** minor - identifies the instance of the device type
** Create device files with mknod command

cd /home/chroot
mkdir {bin,dev,lib64}
cp -p /bin/bash bin/
cp -p /lib/{,,,} lib64/
mknod dev/null c 1 3
mknod dev/zero c 1 5
chmod 0666 dev/{null,zero}

Expand the chroot environment to support rsync

Copy in the rsync binary and required objects

Lock down the shell:

if (( $# == 0 ))
        echo "shell access is disabled"
        exit 1
elif (( $# == 2 )) && [[ $1 == "-c" && $2 == "rsync --server"* ]]
        exec $2

!!! sshd config block:

Match User xfer
	ChrootDirectory %h
	AllowTcpForwarding no
	# Uncomment to force sftp-only connections
	# ForceCommand internal-sftp

!!!! Large services (like apache)

Must be done manually.

Several tools exist to assist with the process.
Example: [[jailkit|]]

Be sure to: 
Remount the logs or set up a bind mount
Create the null and urandom devices

!!! chroot example - Accessing a broken system 

!! Other mount types

!!! bind mount

remount part of the filesystem hierarchy somewhere else

* mount &#045;-bind //src_path// //mount_point//

!!! swap space

Exhausting memory may lead to system crash.
Swap is a overflow area for RAM to prevent that from happening.  

Physical RAM is divided into pages
When the system requires more memory then is physically available, the kernel swaps out less used pages from RAM and provides memory to the application in need.
The swap space is an area on the disk used for storing these less-used pages of memory
Swap downside - disk is extremely slow compared to RAM
Two types of swap spaces:
 - Swap partition - Separate partition used only for swapping
 - Swap file - A file within a normal filesystem used for swap space.  Handy for emergency swap expansion.

Monitor swap status with {{Command{swapon -s}}}

To create a swap partition

Prepare the partition for swap use:  {{Command{mkswap /dev&#047;//partition//}}}
Enable the new swap space:  {{Command{swapon /dev&#047;//partition//}}}

To create a swap file:

First create a blank file with dd:  {{Command{dd if=/dev/zero of=/swapfile bs=1M count=100}}}
(Adjust the count appropriately)

Prepare the file for swap use:  {{Command{mkswap /swapfile}}}

Enable the new swap space:  {{Command{swapon /swapfile}}}

Add your swap space to fstab for activation on boot

General guidelines:
 - Desktop: swap should be 2x physical RAM
 - Server: swap should be 1/2 physical RAM
 - Be sure to monitor how much swap you are using.  You may either need to expand swap or expand physical RAM
 - Adjust depending upon amount of physical RAM.  More physical RAM can mean less swap, less physical RAM may require more swap.

!!Local domain sockets
* Connections between processes
* Created by system call
* Allow a service to safely listen locally for data from other processes without being bound to a network interface
* Communication occurs through the socket file instead of a network port
* Example: Local mySQL database connections
** nagios data injection

!!Named Pipes (FIFO)
* Rarely used but worth being aware of
* Another means of inter-process communication - allows two processes to communicate by reading from / writing to this file
* Unnamed pipe:  ipfw table 2 list | cut -d / -f 1
** The shell is creating an anonymous file to save the output of ipfw and use this file as input to cut
** This unnamed pipe is destroyed once the process ends
* Create with mkfifo command
* Named pipe:  
**Crude Example:
*** mkfifo ips
*** cut -d / -f 1 ips | xargs -n 1 host &
*** ipfw table 2 list > ips
** Reads and writes are blocking: if a process writes to a named pipe, it will get blocked until there is process willing to read that pipe
** More practical use: Script in while 1 loop running as root accepting data from user process (web server?)
** Crude Proxy:  
*** mkfifo proxy
*** nc -kl 4444 < proxy | nc 80 > proxy

Domain sockets are for sending data to services, named pipes are for imitating writing to and reading from a file

!! Filesystem layout

Four structural sections of a partition
*Boot block - where boot program is stored to load kernel into memory
*Super block - Contains information about the file system - number of inodes & data blocks, disk size, number of empty blocks, location of bad blocks
*Inode Block - (Index Node) - contains information (metadata) about each file in the data block
** See metadata with {{Command{stat}}}
**One inode for each file on the disk
**Contain the file's information, such as the owner, file type, permissions, timestamps, and pointers to data blocks that contain the file's data
**The file's name is not part of this metadata.  The name is stored in the directory listing.
**A physical file has only one inode, but it can have many names
**df  -i  command - show inode usage information
**ls -li - show a file's inode number
**A directory is an organizational file list containing the file names and inode numbers of its contents
**Each filesystem maintains its own inode table
*Data Blocks - the actual file contents


*Symbolic (soft) links point to a file by name
**The link only contains the path to the file
**Can span file systems
**Remove the source and the data is gone, even if the link remains.
*Hard links point to same disk area (inode)
**Inode:  Data structure containing the file's metadata (size, times (create, access, modify), owner, permissions, locations on disk (block locations), link count, etc)
**Cannot span file systems
**Remove 1 and the others remain
**File not actually deleted (unlinked) until link count is 0, then its resources are available for reuse

! Assignment

!! Read ~SysAdmin Chapter 13 - Drivers and the Kernel

! References
! Material

!! General Strategy

Servers are different then desktops
* Typically many more concurrent accesses
* Multiuser
* Need for a higher level of availability

First steps:
 - Observe memory utilization
 - Observe disk accesses

Spread the load
* System load balance with multiple servers
* Disk load balance with multiple disks
* Side effect of redundancy 

Understand the configuration options for system and services
* apache / nfs - start more server instances
* trim DNS lookups (web & mail logs)
* Spread data across disks

Address usage issues
* Too many services running on a single system
* Inefficient practices
** Excessive logging
* Cron jobs scheduled for appropriate times, like backups and updates
* Consider lowering CPU priority for background tasks

Understand usage needs & consider faster components
* Number of cores vs clock speed
* Faster RAM
* Faster Disks (SSD, 7200, 10k, 15k)

Monitor your resources to understand their usage
* Know what's in your system
** dmesg
** cat /proc/{cpuinfo,meminfo,diskstats}
* Gather and review historical data
* Logs and performance graphs will help you here

Identify inadequate areas for improvement

!! Performance Analysis Tools

!!! Have a way to:
- measure
- collect
- record
- analyze trends

!!! For all of our resources, understand
- current and normal utilization levels
- whether a resource is saturated
- if errors are being generated

Tracing tools:  [[sysdig|]]


Command line vs. GUI tools
 - Often the GUI tools use the command line backends
 - Graphics are easier to visualize trends

!!! 4 resource areas:
 - CPU
 - Memory
 - Storage 
 - Network

* CPU utilization
** Easiest to monitor
** Load averages with uptime or w
** top command / htop
** ps
*** ps -ef f
** Process priority - niceness
*** The higher the nice value, the lower the priority
*** nice - Launch a process with a different priority
*** Launch //command// with lower priority : nice -10 //command//
*** renice - Change the priority of an existing process
** mpstat - multi-processor statistics
*** mpstat -P ALL 1
** pidstat - Process statistics
** vmstat (via sysstat package)
*** us = user time
*** sy = system time
*** id = idle time
*** wa = waiting for I/O
*** cs = context switches (process changes)
*** in = interrupts per interval
** User activity

* Memory
** Virtual page mapped to either RAM or disk (swap partition)
** Monitor RAM usage to ensure enough physical RAM
** free -m
** top
*** sort by memory usage with ''F''  (field)
** Limit swap, it's expensive
*** swapon -s
** vmstat - Virtual memory statistics
*** vmstat -Sm 1
*** si = pages swapped in
*** so = pages swapped out

* Storage I/O
** Proper partitioning
*** Keep frequently used items close together and near start of disk
*** Don't make the disk heads travel a long distance
** iostat
*** iostat -xmdz 1
** iotop 

* Network I/O
** ping
** traceroute
** netstat
** ntop
** cacti - Record bandwidth utilization
** trafshow / iptraf / iftop
** smokeping - Record latency
** nethogs - Per process network activity

!! Identify processes

kill -STOP / -CONT
(kill -l)

!! Limit users

~FreeBSD: /etc/login.conf

! Assignment

!! Experiment with the performance monitoring tools

!! Continue beating on the last hack box

<<tiddler [[Lab 34 - Bring mail server online]]>>
! Material

!! The kernel
- Core around which all Linux distributions are built
- The layer between the user programs and system hardware. 


Abstract the underlying hardware from the software
Provides a running environment for application software through system calls
Manages interaction with the hardware
 - drivers translate between hardware commands understood by the device and the programming interface used by the kernel
 - keep the kernel device independent 

Two types
* Monolithic - Entire OS runs in kernel space
* Microkernel - Just the core runs in kernel space with most tasks operating as user processes
** Userspace services sit between the kernel and software
** Tanenbaum & Minix debates

Hardware identified:
* Detection on boot
* Periodically while the system is online (USB)

Device files (/dev/)
* Provide user-space access to device drivers
* Operations on these files are mapped into calls to the device driver
** Kernel intercepts the action and transfers control to the appropriate driver
* Pseudo-device - device files that don't map to real hardware
** /dev/null
** /dev/zero
* The device files:
** Type: 
*** block - reads one block at a time (512 bytes)
*** character - reads on character at a time
** Device number:
*** major - identifies the driver associated with the file (type of device)
*** minor - identifies the instance of the device type
** Created on system start
** Manually create with mknod command
* udev - Linux kernel device manager
** Dynamically manage creation and removal of device files
** udevd 
** listens for device status change messages from the kernel (sysfs)
** Configured in /{etc,lib}/udev/
*** Specifies actions to take when a device is attached
*** Examples:  Create a symlink, automount, run a script, 
** Manage udev with udevadm 
*** udevadm info -a -n xvda

* View kernel messages with dmesg command

!! Loadable kernel modules (drivers) - 
* On demand loading/removal of device drivers and extra functionality
* Small pieces of compiled code that can be dynamically inserted into a running kernel
* Modules aren't loaded until they are needed
* Good for temporary use or new hardware
* Keeps kernel slimmer
* Extend functionality without rebuilding kernel and restarting system
* FUSE - bridge between kernel and user-space device drivers
* lsmod
* /lib/modules/
* modinfo - Display info on a kernel module
* modprobe - Add or remove kernel modules
* or, insmod & rmmod
* rootkits
** malware which hooks itself into the system using administrative (root) level access
** Typically kernel modules which hide processes or files from the user to conceal malicious activities
** May also operate above the firewall to allow network traffic 

HP kernel module for bios updates

!! Building a new kernel

When to update kernel: 
* Compelling reason to upgrade an otherwise stable kernel:
* Security fix
* New functionality
* Kernel bug
* Performance / Stability

Productivity gains must offset that lost for updating and restarting the system

!!! Generic kernel

 - Large kernel containing most commonly used drivers
 - Designed to run most applications on most hardware
 - Bloated

yum update

!!! Custom kernel:

 - Slimmer.  Only supports required devices.
 - Increased performance over a generic kernel
 - More difficult to maintain

Inventory hardware
 - must know your system
 - ls /proc/config.gz
 - Make sure every driver vital to the startup of your system (such as disk controllers) is compiled in to kernel and not as a module
 - lspci  (pciutils package)
 - lshw (lshw package)
 - lsmod

Obtain sources 
 - unpack to /usr/src/
 - make help - display all possible targets
 - make mrproper - Clean up build environment
 - make clean - Quick clean of build environment

Configure kernel
 - make oldconfig (optional) - Read config file from old kernel and only ask new questions
 - kernel config file - .config
 - copy from old kernel
 - make menuconfig

 - make -j //N//  (where N = the number of CPU cores)

* make modules_install
* cp arch/x86/boot/bzImage /boot/vmlinuz-//version//-//tag//
* cp arch/x86/boot/ /boot/
** Symbol table.  Look-up between symbol names and their addresses in memory.  Useful for kernel panics
* Edit grub config

initial ram filesystem (initramfs) 
 - a gzip compressed cpio archive
 - Needed to mount the root filesystem 
 - Preload block device modules needed to access the root filesystem
 - and perform any other early actions (encrypted filesystems, load extra drivers)
 - Can also be used to customize the boot process
 - The {{File{init}}} script will be executed to perform these tasks

!! Tuning the kernel

Kernel configuration:
* tuning parameters
** Edit files within /proc/sys
*** Enabled immediately but lost at reboot.
*** Good way to test changes
** sysctl
*** See all available tunables:  sysctl -a
*** Make changes permanent:
*** Edit /etc/sysctl.conf
*** sysctl -p
* Easy example: Tune swappiness

! Assignment

!! Read ~SysAdmin Chapter 20 - Email. Stop at section 20.8 on page 775.

<<tiddler [[Lab 35 - Install Exim]]>>

! Material

Hosted vs. onsite

User agent (mail client)
MSA - mail submission agent
MTA - mail transport agent (sending server)
*receive email from remote servers
*forward messages to the responsible server or pass to a delivery agent
mta - (receiving server)
Delivery agent (receive and store message)
Access agent (pop/imap)


MTA Stats
Security space MX survey

Mail is all text
binaries are mime encoded

SMTP - Standard SMTP protocol
ESMTP - Extended SMTP protocol
 - encryption
 - authentication

forging headers
plain text communication
encrypt mail yourself

Message stores
*mbox - One file for all mail
*maildir - One file per message
*database - ~mySQL ?

access agents
pop - Post Office Protocol - grab all mail at a time
imap - Internet Message Access Protocol - one message at a time
 - browse headers and only download messages you're interested in
 - better with attachments

Mail message breakdown
Envelope - describes where the message will be delivered or bounced to
Headers - property/value pairs describing information about the message
Body - textual content of the message

DNS mx resource records
 - specifies which server accepts mail for the host

Headers of legit mail and spam
* Samples
* [[Ron's Email|demo/ronemail1.pdf]]

SMTP Commands
usage from command line
see table 20.2, page 751

mail aliases
*single users or lists of users
*file containing a list of addresses (:include:/etc/mail/email_list)
*file to append to
*command to run with message as input
*standard administrative aliases
*alias mechanisms
**flat files
***site alias files
***user alias - ~/.forward

!! Filtering mail

Incoming MTA filtering (ordered by cost of processing, check quick and easy first)
 - RFC compliance (early talkers)
 - sending site is blacklisted
 - local recipients are invalid
 - reputation checks
 - spf or dkim records are invalid
 - filter mail for spam (compare content to known expressions)
 - filter for virus

What to do with bad messages
- bounce
- drop
- archive
- quarantine


Junk or malware

Responding to mail messages
backscatter spam - spam messages spoofed from you which are bouncing

Spam filtering strategies

 - ~RBLs, 
 - DNS based, 
 - Also DNS based
 - lists of sites with a good reputation
 - reduce scanning overhead
 - reduce false positives
greylisting - defer all connections
spamassassin - point based filter rule system
mail filters (milters) - scan headers and body
 - third party tools for mail filtering
 - mostly sendmail and postfix
spf / dkim checks

SPF - sender policy framework
DNS records an organization can use to identify its official outbound mail servers
refuse, rate up, or rate down messages depending on check results
relaying mail breaks this!

DKIM - domainkeys identified mail
cryptographic signature system using public/private keys
also DNS based
verify senders identity

!! Mail server software

Mail submission agent or mail transport agent
The host's MSA listens only on localhost

Top three are made to be compatible.
 - common alias and .forward files
 - similar capabilities

!!! sendmail
original, written by a Berkeley grad student
notoriously insecure and more difficult to configure
Fallen out of favor
Still the default for ~FreeBSD

!!! Postfix - Security as main focus
simpler and faster
series of small programs instead of one large one
Default for some Linux distros

!!! Exim
more configurable and powerful
interfaces directly with common mail spam/virus scanners
enable extra options at compile
Also the default for some Linux distros
per-user filters
~ACLs can define policy
 - check blacklists
 - verify valid user & domain
 - check content
Routers & Transports do the bulk of the work
Routers - decide how messages should be delivered (ordered list)
 - work on email addresses
 - examine username and domain in order to determine where to send the message
 - possible dispositions: accept, pass, decline, fail, defer, error  (pg 821)
 - local users
 - aliases
 - forwarding
 - decide which transport to hand off to
Transports - Responsible for making the delivery
 - save to a user mailbox
 - append to a file
 - send to a program
 - send to a remote system
 - shouldn't need to change defaults

!!! Bring exim online:

* Adjust config
** Set local domains : //username// : *.//username//
** Allow relaying: 10.103.36.x/29
* copy exim init.d script
** wget -O /etc/init.d/exim
* create exim log dir & set permissions
* Check /var/mail directory & set permissions
* Ensure we have MX records for the domain:
** dig mx //username//
* Test user account
** id //username//
* Ensure NFS home directory exists
* Enable startup on boot:
** chkconfig &#045;-add exim
** chkconfig exim on

Install mailx and do some testing

Log files:
* /var/log/maillog
* /var/log/exim/

!!! Configure relaying

configure postfix on other systems to relay mail through your mail server
Edit the /etc/postfix/
Search for relayhost

!!! Expand exim config:

Adjust the ~ACLs

# Reject mail from locally blacklisted IPs.
deny   hosts =        /opt/work/exim/etc/blacklist_ip
      message =      Rejected
       log_message =  Rejected [BLACKLIST] $sender_host_name ($sender_host_address)

# Reject mail from blacklisted senders.
  deny  message = $sender_address denied access.
       log_message =  Rejected [BLACKLIST] $sender_address from $sender_host_name ($sender_host_address)
        senders = /opt/work/exim/etc/blacklist_address
        delay = 3s

Add a router:
    driver = redirect
    domains =
    senders = ${if exists {/opt/work/exim/etc/lists/$local_part-senders}\
    file = /opt/work/exim/etc/lists/$local_part
    errors_to = $sender_address

!!! Some References

! Assignment

<<tiddler [[Lab 36 - Configure exim and bring online]]>>
<<tiddler [[Lab 37 - Add Anti-Spam support]]>>

! Today's Material

!! System Startup

*Boot process - ~SysAdmin Chapter 3
**BIOS (Basic Input/Output System)
*** For motherboard and certain devices
**MBR (First block of the disk)
**Boot loader
*** Grub - Grand Unified Boot loader
*** Check out grub configs in /boot/grub
*** Use it to boot multiple kernels (such as after a kernel update) or multiple ~OSes
** kernel - /boot/vmlinuz* - loaded into memory and begins to execute
*** Press ESC to see boot messages
*** device detection: probe system buses, inventory hardware, and load device driver modules
*** create kernel processes (those in brackets)
*** system becomes available for user processes once the kernel is loaded
**init - First user process - parent of all processes running on the system
*** executed by the kernel and responsible for starting other processes
**startup scripts - start system services

*init and runlevels
** PID 1
*** check out man page for kill
*** kill -2 1
**init 0 - shut down
**init 1 - single user mode
**init 2 - single user with networking
**init 3 - full multiuser
**init 6 - reboot
*** Last line is default runlevel
*** Experiment with the run levels
*** {{Command{telinit}}} command can be used to change runlevel
*** {{Command{runlevel}}} command can be used to display current runlevel
*** Log in via SSH and incrementally reduce runlevels
*Service / system startup scripts
**/etc/init.d/ scripts
*** Can run scripts directly or through the service command
*** See a service's status with {{Command{service iptables status}}}
*** Stop iptables with {{Command{service iptables stop}}}
**/etc/rc.*/ scripts
*** rc = Run commands
*** Symbolic links to scripts in /etc/init.d
*** Begin with S (start) or K (kill) and a sequence number to control their start/stop order
*** They (minimally) accept start/stop/restart arguments
*** /etc/rc.d/rc.local - Executed at boot or when changing runlevels. (Legacy)
**Manipulate symlinks directly or with the chkconfig command
**Disable iptables from starting on boot with {{Command{chkconfig iptables off}}}
**From within single user:
*** No network
*** No services
*** Run init 3 to bring online
*Configure init
**Look at /etc/init/ directory
*** Disable ~CTRL-ALT-DEL reboot
** /etc/sysconfig/init file
*** Force authentication for single user mode
*** Change sushell to sulogin
** {{Command{initctl reload-configuration}}}
*Config files in /etc/
** Most are single files for the service or resource
*** fstab : tab = table - filesystem table
*** resolv.conf
*** sysconfig directory - extra system configuration files
** Some are multiple files
*** cron is a good example
*** crontab - traditional cron config table
*** cron.d - directory containing individual config files
*** cron.{daily,monthly,weekly}

* How to access systems if problems occur during boot
** Boot from a live CD or recovery mode
** Single user mode
*** First change the grub timeout to 20 seconds
*** While we're here, remove ''rhgb quiet'' from the kernel line in {{File{/boot/grub/grub.conf}}} to disable the progress bar
*** Press enter on system boot to see grub menu
*** Highlight desired kernel and press a to append a command
*** Add the keyword  {{Command{single}}} to the end of the line.

Commands:  shutdown, halt, reboot, and sync


!! Read ~SysAdmin Chapter 12 - Software Installation and Management
* Skip over sections for other ~OSes
* Be sure to understand the difference between the rpm and yum tools
<<tiddler [[Lab 03 - Install man]]>>

!See Also

~SysAdmin Chapter 6 - The Filesystem

!!NCS Club Linux workshops
* Thursday, Jan 29 12:00 to 1:30
! Material

!! Remote access

!!! Working with SSH

!!!! SSH Host Keys

* Public key crypto used for encrypting communication between client and server
* Server keys are stored in /etc/ssh/ssh_host_*
* Fingerprints for new systems are shown and stored in ~/.ssh/known_hosts 
** This file can leak identities of systems you are communicating with
** Hash your current known hosts file : ssh-keygen -H
* Fingerprints for known systems are compared on each login to identify MITM attacks
** The user is alerted if a mismatch is found
** They should take steps to verify the host key has legitimately changed.
** {{Command{ssh-keygen -lf  //file//.pub}}}

{{Command{cd ~/.ssh/}}}
Change to the .ssh/ directory, the default location for ssh client files.

{{Command{ssh bingo}}}
Try to connect to bingo.  You should be prompted to accept its host key if this is your first time accessing it.

Press ~CTRL-C to terminate the connection.  You do not need to authenticate

{{Command{grep bingo known_hosts}}}
Scan your known_hosts file for bingo's fingerprint.

{{Command{ssh-keygen -H}}}
Hash your known_hosts file and try your grep command again

!!!! SSH access via keys:

* Users can use key pairs for authenticating to the remote system.
* More secure use of passphrase instead of just a password
* User creates their own public / private key pair
** {{Command{ssh-keygen}}}
** Must possess the private key file in order to connect
** Public key is distributed to the remote systems and saved in {{File{~/.ssh/authorized_keys}}}
** Default private key file name is {{File{~/.ssh/id_rsa}}}

!!!! Setting up a keypair for our ~VMs

{{Command{cd ~/.ssh/}}}
Change to the .ssh/ directory, the default location for ssh client files.

{{Command{ssh-keygen -f  cs407}}}
Create a SSH key pair using default settings, but naming the key cs407.  The algorithm and key size can also be adjusted via flags.  The defaults are reasonable.

On your test and www ~VMs:  {{Command{mkdir ~/.ssh/}}}
Create the user ssh directory if it does not already exist.

{{Command{scp root@10.103.36.''x'':./.ssh/authorized_keys}}}
Copy your public key to each of your VMs, saving it to the authorized_keys file

{{Command{ssh -l root 10.103.36.''x''}}}
Try to connect to your test VM.  You should be prompted for a password since our private key is not in the default location and was not specified on the command line.

{{Command{ssh -i cs407 -l root 10.103.36.''x''}}}
You should now be prompted for your SSH passphrase instead of password.  If a available and authorized SSH key is found it will be offered for use instead of your password.  Authentication will fall back to regular password if key-based fails.

Disconnect from your VM

Having to specify the username and key file to use for each login to your ~VMs can be eliminated by using a ssh user client config.  Edit {{File{~/.ssh/config}}} and set a default username and ssh key for class ~VMs

(''Warning'':  This will overwrite the file if it already exists)
cat > ~/.ssh/config << _EOF
Host *
        HashKnownHosts yes

Host 10.103.36.* *
        IdentityFile ~/.ssh/cs407
        User root

!!!! SSH agent - Unlock your key once for multiple connections

The SSH agent is keyring which your SSH private keys can be attached to.  Once set up, future connections will look to that key ring when an authentication request is made instead of prompting you for your SSH passphrase.  The idea is one authentication event for many remote connections.

{{Command{ssh-agent > ~/.ssh/env}}}
Create a SSH agent, saving the environment information to the specified file.  This environment must be imported in order to make use of the agent.

{{Command{eval `cat ~/.ssh/env`}}}
Import the environment settings into the current shell environment

{{Command{ssh-add ~/.ssh/cs407}}}
Add your cs407 private key to your ssh agent keyring

Once the SSH agent is established you may communicate to many systems without being prompted to authenticate

!!! Terminal multiplexing with GNU {{Command{screen}}}

GNU {{Command{screen}}} is very useful tool for those working with the command line on many systems from different locations on a daily basis.  From within {{Command{screen}}} connections can be made to many systems.  The user can detach from the screen session, change physical locations, and reconnect to their screen session continuing work where they left off.  GNU {{Command{screen}}} and ssh agents make a great combination for connecting to multiple machines over the course of your work day.

{{Command{cp ~nick/.screenrc ~/}}}
Copy this default screen configuration file to your home directory.  This will establish some baseline settings

Once connected to fang with your SSH agent active, run {{Command{screen}}}

Screen commands:
| !Key Sequence | !Action |
| ~CTRL-a , 0 |Switch to window 0|
| ~CTRL-a , 1 |Switch to window 1|
| ~CTRL-a , 2 |Switch to window 2|
| ~CTRL-a , c |Create a new screen window|
| ~CTRL-a , " |Display available screen windows|
| ~CTRL-a , ' |Switch to a screen window by number|
| ~CTRL-a , T |Title the current screen window|
| ~CTRL-a , ? |Display screen help|

Switch to window 1 and connect to your test VM
Switch to window 2 and connect to your www VM

Create a new screen window
Title it __auth__

Switch to your test VM

More screen commands:
| !Key Sequence | !Action |
| ~CTRL-a , &#124; |Split window vertical|
| ~CTRL-a , S |Split window horizontal|
| ~CTRL-a , TAB |Switch between split windows|
| ~CTRL-a , X |Close a split window|
| ~CTRL-a , d |Detach from screen|
| ~CTRL-a , :password |Set a password for your screen session|

{{Command{screen -dr}}}
After reconnecting to fang, run this command to resume your screen session.

Detach from screen
exit terminal completely
ssh back into fang
Resume screen

! Assignment

Ensure last week's assigned reading and labs are completed.

! Extra learning
NCS Club Linux shell scripting - Thursday at noon in C012.


Document your network and track changes to each system as they are made
 * How things are configured and set up
 * Inter-dependencies between software, processes, or systems
 * Modifications to configuration files  (What file, what change, why the change was made)
 * Software installed or removed
 * Major software updates (kernel, OS, or important packages)
 * System changes (such as filesystem modifications)
 * Also record commands used so you can easily repeat your steps

Start keeping good notes of what you are doing with your ~VMs.  These notes will be added to a wiki we will be setting up next class.

Revision control:
* Subversion
* Git
* fossil
* Mercurial

Configuration management and distribution:
* cfengine
* puppet
* Ansible
* Salt stack

!! Expanding our systems - ~SysAdmin Chapter 12

!!! The yum package manager

Package management is one of the customized components of a linux distribution and differs between unix operating systems and linux distributions

Core components of a Linux distribution are:
* Linux kernel
* Base utilities (typically GNU tools)
** Many g* utilities are from the GNU project (eg: gcc)
** Stallman's GNU (GNU's not Unix) project, early 80's.  Wanted to create a totally free OS. Started with the utilities.
** Came from the Free Software Foundation and [[a philosophy of freedom|]] (freedom (speech), not price (beer) ).
** Software should be free to run, change, copy and modify so users are the ones in control, free from corporate control so better software develops - GNU license
** Differ somewhat from ~FreeBSD tools (sed is a good example)
* Package manager.

Extra (optional) components:
* Specialized utilities
* X server / Window manager

Each distribution combines these components in different ways depending on their focus and goals.

~CentOS (and Redhat based systems) use the RPM package format and rpm package system with the yum package management utility.

Other package management systems exist for other distros
 - apt  (Debian)
 - portage  (Gentoo)
 - ports  (~FreeBSD)
 - ~DistroWatch [[Package management cheat sheet|]]

rpm - very basic utility
* It will mainly just install, update, or remove packages
* You will need to acquire the .rpm package file yourself or have a direct URL for it
** A .rpm file is a collection of pre-compiled binaries, configuration files, and support files for an application compiled for the target architecture.
* Conflicts and dependencies will need to be sorted out manually

yum - high level utility for package management
* will interact with repositories (collections of .rpm files) to obtain packages
* takes care of any conflicts
* will install necessary dependencies
* records what is installed and any changes made to the system to facilitate updates, package removal, or audit.

Different package repositories (repos)
* Repository configuration files are stored in {{File{/etc/yum.repos.d/}}}
* A repository is the central distribution point for our linux packages
* Typically, each distro has its own repository on the internet for base packages
* The repository creator determines which applications it contains
* Repos are mirrored for accessibility and speed.
* The CS dept is running a local mirror of the ~CentOS repo
* Other repositories offer additional packages

EPEL (Extra Packages for Enterprise Linux)
Distributed by the Fedora Project to offer a repository of add-on packages

Don't run this until we need the EPEL repo 
{{Command{rpm -ivh}}}

Other specialized repositories may exist:
 - HP repo for their utilities (raid utils)

!!! Yum package manager commands:

The primary command for the yum package manager.  Run this by itself to see all sub-commands

{{Command{yum check-update}}}
Check the repositories for any available updates and display the results, without applying an updates.

All updates and software additions are coming from a repository mirror off campus.  To speed things up, we'll use the ~DogNET ~CentOS repository mirror.  Create this file to utilize our local repository instead:

Create the file {{File{/etc/yum.repos.d/cs407.repo}}} and save the following text:
name=CS407 CentOS 6 Repo

{{Command{yum repolist}}}
Display the configured repositories

Run {{Command{yum check-update}}} again.
You should now see a list of updates with ~DogNET specified as their source.

{{Command{yum update}}}
Check the repositories for any available updates.  After reviewing the results, the user will be prompted to apply them.  A {{Command{reboot}}} will be required if a kernel update is included in the list.  Otherwise, only updated services may need to be restarted for the updates to take effect.

!!!! yum cleanup:
{{Command{yum clean packages}}}
Remove cached packages after install is completed.  ''Please run this after installing or updating software''

{{Command{yum clean metadata}}}
Remove the XML metadata cache

{{Command{yum clean dbcache}}}
Clean the yum ~SQLite database

{{Command{yum clean all}}}
Remove all cached yum content

{{Command{yum makecache}}}
Download and rebuild the repo metadata cache

{{Command{yum update //package_name//}}}
Update a single package

{{Command{yum provides "*/ssh"}}}
See which package provides the file named ssh. 

{{Command{yum info //package_name//}}}
Display information on the specified package

{{Command{yum install //package_name//}}}
Install a package from yum

{{Command{yum search //string//}}}
Search the repository for packages matching //string//

{{Command{yum deplist package_name}}}

{{Command{yum list installed}}}

{{Command{yum remove //package_name//}}}

* Yum package groups:
** {{Command{yum grouplist}}}
** {{Command{yum groupinfo //group_name//}}}
** {{Command{yum groupinstall //group_name//}}}

* Yum plugins
** Extend the functionality of the yum package manager
** See available plugins with {{Command{yum search yum-plugin}}}

yum-plugin-security - Check currently install software for security updates.  Requires a subscription.

{{Command{yum &#045;-security check-update}}}
{{Command{yum &#045;-security update}}}

{{Command{yum updateinfo list available}}}
{{Command{yum updateinfo list security all}}}

We can install most required software using packages with yum:
* Keep a record of what is installed as we go.
* Get started with: 
** Install on all systems: man wget nc telnet bind-utils openssh-clients rsync
** Add to the web server: gcc make perl

We can also install software directly from source archives
* Source archives are typically distributed as compressed tarballs
* Latest versions are not always available via package
* Building from source allows for additional customizations
* and a higher level of control
* Multiple versions of a program can easily be maintained on the same system by installing to different locations
** But you must keep them up to date (patched) and sort out any dependencies manually.

We will now install the Apache web server with PHP module from source:
* Apache - - Download the latest version of the 2.2.x branch
* php - - Download the latest version

!!! Installing apache, mySQL, and php  (LAMP stack):

Check hostname with {{Command{hostname}}} command and set it if necessary.

Create the directories /opt/src/ and /opt/work/ 
* Save the source tarballs to /opt/src/
* Custom built software will be installed within /opt/work/

Check out all available configuration options:
{{Command{./configure &dash;&dash;help}}}

Configure options for apache:
./configure \
  --prefix=/opt/work/apache_2.2.29 \
  --enable-module=so \
  --enable-ssl \

Compile it: {{Command{make}}}
Install it: {{Command{make install}}}
Clean up: {{Command{make clean}}}

After installing:
* Create apache symbolic link in /opt/work/
* start apache with the {{Command{apachectl}}} command located in {{File{/opt/work/apache/bin/}}}
** We have to start/stop/restart apache manually since we did install an init.d script
** Packages installed via yum will come with one.
** {{Command{apachectl start|stop|restart}}} to control apache
** run {{Command{apachectl}}} by itself to see available options
* Verify the service with the {{Command{telnet}}} command
* Also check out the {{Command{curl}}} and {{Command{nc}}} commands
* Verify connectivity from your workstation

{{Command{telnet localhost 80}}}

Then view apache log files to verify the connection.

Install php from source
Configure options for php:
./configure \
  --with-apxs2=/opt/work/apache/bin/apxs \
  --with-config-file-path=/opt/work/apache/conf \
Running the ./configure script will highlight any additional dependency issues to sort out.  

make install
make clean

Or, use a short circuited conditional:  {{Command{make && make install && make clean}}}

Install mySQL Server:
* Install mySQL server from package with yum
* Start the mySQL service 
* Enable mySQL server startup on boot

Configure apache to use php
* Edit the apache configuration file, httpd.conf, located in /opt/work/apache/conf/
* Search for the ~DirectoryIndex directive and add the string {{Command{index.php}}} to the end of the line
* Reference the configuration file on the CS dept web server (hostname spike) to finish configuring apache to support php.

Don't forget to restart apache using the {{Command{apachectl}}} command after changes are made to its configuration file.
 - {{Command{apachectl}}} will verify the syntax of the configuration file before restarting the service

! Assignment

!! Lab & VM wiki:
* Start keeping good notes of what you are doing with your ~VMs.
** Adding the cs407 repo and software installed today should be included.
* These notes are to be added to a wiki you will maintain on your web server.  We will be installing it next class.
* This lab wiki will be part of your overall lab grade for the course

<<tiddler [[Lab 04 - VM updates & software installation]]>>
<<tiddler [[Lab 05 - Web Server]]>>

!! Reading

Read ~SysAdmin Chapter 2.1 - Shell Basics

!! Outstanding

Project topic selection is due Feb 20.

!Additional Material

!! Online lab Verification

Nagios checks (on campus only, for now)

!! Useful commands:
* wget
* tar
* telnet
* curl
* apachectl

! References

! Material

!! Working with the shell


Shell is what users interact with on the command line.  Receives and interprets commands. 


There are two main families, the bourne and ~C-Shell

bash (Linux) vs tcsh (~FreeBSD)

Available system shells are listed in the file {{File{/etc/shells}}}
 - {{Command{/sbin/nologin}}} : A shell used for disabled accounts

!!! Bash Customization

RTFM!  {{Command{man bash}}}

!!!! Shell initialization and configuration scripts - executed upon login

Interactive login shell execution sequence: 
(When you first log in to the system)
* /etc/profile.d/*
* /etc/profile 
* ~/.bash_profile 
* ~/.bash_login 
* ~/.profile 
* //User disconnects//
* ~/.bash_logout

Non-login shell execution sequence
(manually executing {{Command{bash}}} or opening a graphical shell)
* ~/.bashrc 

{{Command{source //file//}}} (or {{Command{. //file//}}})
Read and execute commands from //file// in the current shell environment.  Apply changes to an environment file to the current login shell.

!!!! Shell configuration files:

Readline library - A library for reading a line of input from the terminal 
 - Configured by {{File{/etc/inputrc}}} and {{File{~/.inputrc}}}
 - These files mostly control additional key bindings

Configure directory listing colorization
Disable ls colorization on the ~VMs
 - vi /etc/~DIR_COLORS
 - change tty to none

{{File{/etc/motd}}} - A ''m''essage ''o''f ''t''he ''d''ay to display to users after they log in

!!! Aliases

Display currently defined aliases:  {{Command{alias}}}

Set an alias:  {{Command{alias name='long_cmd -abcd | next_command -efgh'}}}

Standard aliases
 - ll

Override aliases:
 - rm
Prefix your command with a \ (backslash) to suppress alias expansion:  {{Command{\rm foo}}}

Disable an alias:  {{Command{unalias //alias//}}}

{{Command{which}}} and {{Command{type}}}
- Display how each argument would be interpreted if executed as a command

!!! Core shell options:

Stored in the $SHELLOPTS variable
Manipulated with the set command

Enable a shell option:  {{Command{set -o //option//}}}
Disable a shell option:  {{Command{set +o //option//}}}


Toggle command line input method between vi and emacs:
{{Command{set -o vi}}}
{{Command{set -o emacs}}}

Enable noclobber:
With noclobber enabled, an existing file will not be overwritten by redirecting STDOUT to a file 
{{Command{set -o noclobber}}}
{{Command{set +o noclobber}}}

!!! Extra shell options:

 -s to enable an option
 -u to disable an option

shopt -s cdspell
shopt -s checkjobs

!!! Environment & Shell variables

In bash, variables are defined on the command line with this syntax:  {{Command{variable=value}}}
By default all variables are local and will not be inherited by child processes

The {{Command{export}}} command will make a variable global and accessible to any child process
{{Command{export}}} can be used when defining a global variable.  eg:  {{Command{export foo=bar}}}
Or, can be used to elevate a currently defined variable to global.  eg:  {{Command{foo=bar ; export foo}}}

{{Command{set}}} will display all currently set variables

{{Command{unset}}} can be used to unset a variable

The shell environment can be manipulated through variables:

For example, the $PATH and the prompt:

Add the apache bin directory to our $PATH

The prompt:

~PS1 - Primary prompt string
Other PS variables exist.

prompt last character - # vs $
 - Show $ for regular users or # for superuser.

A customized colored prompt I like for this class:
#PS1='\n[\u@\h \w] :\n\$ '
PS1='\n[\e[1;31m\u@\h\e[m \w] :\n\$ '

!!! Functions:
- bak function

Append to your .bash_profile
function bak() {
        cp "$@" "$@".`date +%y%m%d:%H%M`.bak

!!! History substitution:

- Your command history is saved in a buffer for the current session
- By default, the buffer is appended to {{File{~/.bash_history}}} upon logout
- Display the current session's history buffer with the {{Command{history}}} command.

History configuration variables:
  - {{Command{set | grep HIST}}}
Examples of history substitution:
!! - Access the previously executed command string
!$ - Access the last argument of the previous command
!cmd - Execute the last command beginning with //cmd//
!123 - Execute history item 123

Test command substitution: 
 - {{Command{date +%y%m%d}}}
 - {{Command{cp file.txt file.txt.`!!`.bak}}}

!!! Some useful Commands

id and whoami commands, w

script command

Using less
 - searching up and down
 - moving around
  -  g / G
  -  space / b
  -  markers    m[a-z] to set  ,  '[a-z] to jump

!!! Moving around the command line

|>| !Must know |
| Up Arrow |Backward through command history|
| Down Arrow |Forward through command history|
| ~CTRL-c |Terminate the currently running process|
| ~CTRL-z |Suspend the currently running foreground process|
|>| !Good to know |
| ~CTRL-a |Jump to the beginning of the line|
| ~CTRL-e |Jump to the end of the line|
| ~CTRL-u |Clear the entire command line|
| ~CTRL-l |Clear the screen|
|>| !Speed things up |
| ~ESC-b |Jump one word backward|
| ~ESC-f |Jump one word forward|
| ~CTRL-w |Cut one word backward|
| ~CTRL-k |Cut from cursor to end of line|
| ~ESC-d |Cut one word forward|
| ~CTRL-y |Paste most recently cut text|

!! The filesystem

umask - assign default permissions to newly created files

!!! Layout of the system

!!! Filesystem from a user's perspective:

/bin - Essential user command binaries (required for system startup or single user mode)
/home - User home directories
/tmp - Temporary files
/usr  - Files residing in /usr are additional, general purpose binaries and libraries not required for system startup 
 - /usr/bin - Additional user command binaries 
/tmp - Temporary files

!!! Administrative Additions:

/boot - Boot loader files and the kernel - Files required for the boot process before user-mode programs begin executing

/etc - Host-specific static configuration files
/opt - Additional optional software packages and files
/root - Home directory for the root user
/sbin - Essential system binaries (required for system startup or single user mode)
 - /usr/lib - Programming libraries
 - /usr/local - Local additions to the system.  Isolated also to prevent overwrite on system update.  (ie: ssh)
 - /usr/sbin - Binaries for system administration and repair
 - /usr/share - Architecture independent static data files (ie: dictionaries, man pages, examples)
/var - Variable data files, system specific - spools, logs, transient files, and system data unique to the system
 - /var/mail - User mailboxes
 - /var/run - Runtime data.
 - /var/spool - Application spool data
/dev - Device files - A means to interact with and pass information on to the hardware device drivers or the kernel
/proc - Kernel and process information virtual filesystem
/mnt - Temporary filesystem mount point

See also:
~SysAdmin Table 6.2 on page 147

!!! File types:

In the Unix world everything can be represented by a file

First character in the output of {{Command{ls -l}}} 

| !Symbol | !File Type |
| - |Regular files|
| d |Directories|
| l |Symbolic Link|
| b |Block device files|
| c |Character device files|
| s |Local domain Socket|
| p |Named Pipe|

! Assignment

<<tiddler [[Lab 06 - Customize your environment]]>>

<<tiddler [[Lab 07 - Lab return shell script]]>>

!! Read ~SysAdmin Chapter 23 - Web Hosting

! Catch up

Apache configuration to get us to our current point.
* Enable php
* Change {{File{htdocs}}} location

! Material

!! Web Services 

Web server packages - 
** Apache - LAMP stack (Linux, Apache, mySQL, PHP)
** nginx - Lighter weight for higher performance, speed, and reduced memory footprint
** python - {{Command{python -m ~SimpleHTTPServer [port]}}}
** IIS - MS Windows web server
** [[Netcraft Web Server Survey|]]

{{File{htdocs}}} directory - hypertext docs - The root of our web site

Default page:
* {{File{index.html}}}, {{File{index.php}}} or whatever we define via the ~DirectoryIndex option
* Or a list of files if no file specified by the ~DirectoryIndex directive is found

Process ownership
* {{Command{ps aux | grep httpd}}} - Apache runs as an unprivileged user
* Any scripts executed will run as this user
* This protects the system from malicious or vulnerable scripts

* Extra information sent by the web server describing the connection and server data

# nc localhost 80
GET / HTTP/1.0   

HTTP/1.1 200 OK
Date: Mon, 16 Feb 2015 20:23:55 GMT
Server: Apache/2.2.29 (Unix) mod_ssl/2.2.29 OpenSSL/1.0.1e-fips PHP/5.6.5
Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT
ETag: "4b62-2c-3e9564c23b600"
Accept-Ranges: bytes
Content-Length: 44
Connection: close
Content-Type: text/html

<html><body><h1>It works!</h1></body></html>

* Multiple web sites per server
** IP based virtual hosts - A single server and apache instance will be accessible by multiple IP addresses with each IP address linked to a different web site
** Name based virtual hosts - Multiple host names resolve to the same IP address.  Examine the hostname in the HTTP headers to determine which site to serve.

!!! Apache Modules
* Addons to Apache
** Static - Compiled in to Apache.  Apache must be recompiled to add support for new modules or to update them
** DSO - Dynamic Shared Objects - Compiled separately and loaded when apache starts
** apxs (Apache Extension tool) - A perl script to assist with building and installing apache DSO modules
** PHP was added as an Apache DSO module
* Check available modules
** Those compiled in: {{Command{./apachectl -l}}}
** Available as DSO: {{Command{ls modules}}}
* Add new modules with apxs
** {{Command{apxs -c mod_foo.c}}}
** {{Command{apxs -ian foo}}}
** Must then add a ~LoadModule directive to the apache config file
* Module examples:
** php
** mod_rewrite
** mod_security
** mod_limits
** mod_headers
** Authentication modules

!!! Apache configuration

!!!! Server level
Main configuration file {{File{conf/httpd.conf}}}
Configuration extras - {{File{conf/extras}}}
* Included from the main configuration file (near the bottom)
* A quick way to make common additional functionality available
* ie: SSL support, virtual hosts, user web sites, 
* and Server information:
** /server-status
** /server-info

!!!! User level
.htaccess files - Modify permitted configuration values per directory

!!! php configuration
A separate configuration file to tune php

!!! Scripting
* A means to develop applications to generate dynamic web content 
* php - Standard server side scripting language for web development
** Change your index.html to index.php and add the phpinfo(); php function 
# cat index.php
// The line above instructs the php module to start processing php scripting
phpinfo();		// This function will display information and configuration for our php installation
// The line below instructs the php module to stop processing php scripting.
* perl - CGI scripting - an older method for developing web applications and generating dynamic content
* scripts run either as the apache process (for modules) or as the owner of the file (CGI with suexec)

Keep web applications up to date!
* Security vulnerabilities are constantly discovered in web applications
** mediawiki just came out with one
* These vulnerabilities become attack vectors against the hosting server

!!! Extras

Basic HTTP is stateless: 
* Client makes a request, sever responds, connection closed.
* cookies and session files

Content Distribution Networks (CDN)
* Globally or nationally distribute static content close to the end user
* Akamai

!!! Installing ~MediaWiki

Download from the [[MediaWiki web site|]]
Save it to /opt/work/htdocs/ 
Extract the tarball
Rename the base directory from ''mediawiki-//version//'' to ''wiki''
Test ~mySQL database access from the command line using your wiki credentials
Access your website at http://your_ip/wiki/ to begin the configuration.

!! Bypassing firewalls with proxies and tunnels

We have two good options for connecting to a remote resource behind a firewall:
*SOCKS proxy via SSH
*SSH tunnel to privoxy on fang

*A proxy is a middle man, passing on network requests to their destination on your behalf.
*A tunnel establishes a direct point to point connection between the pairs of hosts.  Half will be encrypted by SSH and the other half will not.

!!! SOCKS proxy with ~OpenSSH

A SOCKS proxy (socket secure) is a protocol to route packets between a client and a server through an intermediate proxy.  This is used (typically for web traffic) when the client is not able to communicate with the server directly, but the client can communicate with the proxy system and the chosen proxy can communicate with the server.  Some sites set up a proxy for web traffic as a means to enforce policy, monitor traffic and block direct connections to web sites.

SSH can be used to establish a SOCKS proxy.  This functionality is only available from the command line ~OpenSSH and requires either a Unix/Linux or Mac system.

This command will create an encrypted proxy tunnel between your PC and the specified host, in this case fang.  Traffic connecting to your PC on port 8118 will pass through this proxy:
Set up SOCKS proxy:  {{Command{ssh -D 8118 fang}}}

Firefox must be configured to pass traffic through the encrypted proxy
Tools / Options / Advanced / Network / Settings
Manual Proxy Configuration
 - http proxy if using a tunnel: localhost:8118
 - or SOCKS proxy: localhost:8118
Adjust firefox settings to resolve DNS on remote side:
 - on URL bar:  about:config
 - search for: remote_dns
 - Double click to change value to true

!!!! Demo:
[[Cacti|]] is a complete network graphing solution ... for ~LAN-sized installations up to complex networks with hundreds of devices.

We can't access this resource directly but can connect to a system which can.
 - Establish the proxy
 - Check for a complete connection with telnet command
 - Configure firefox to use it.

!!! Tunneling connections with ~OpenSSH

A tunnel establishes a direct point to point connection between a pair of hosts.  The first stage will be encrypted by SSH and the second will not.

privoxy is running on fang for proxying web connections but is only bound to the localhost interface.  External users cannot access it without tunneling to it.


Unix/Mac:  {{Command{ssh -L 8118:localhost:8118 fang}}}
Windows:  putty - [[DogNET Help doc|]]

!!! Firefox portable
A second self contained copy of firefox is useful for accessing class resources through the proxy while leaving your primary browser's settings untouched.

[[Firefox Portable|]]

!!! VPN

! Assignment

!! Web Server

See [[Day 4]] assignments for the Lab 5 description.

<<tiddler [[Lab 08 - Set up MediaWiki]]>>
<<tiddler [[Lab 09 - Bring auth VM online]]>>
!! Reading

~SysAdmin Chapter 11 - syslog and log files

!! Goals for next week

Your wiki should be online and accessible for next week's class.  You should be starting to use it for documenting your network and ~VMs.
It should contain:
* Rapid setup - a page documenting the necessary steps and commands for bringing a new VM online.  This page will be expanded as we expand our ~VMs baseline throughout the semester.
** Include such things as IP addressing, default yum repos, standard software packages to install, authentication, logging, and storage.
* Configuration notes - Any notes necessary for configuring particular services unique to a VM
* Changelog - A record of changes made to your ~VMs.

Next week we will be configuring DNS.  Naming a server is a standard sysadmin function.  Start thinking of a naming scheme for your systems.

!See Also

~SysAdmin Chapter 22.7 (Page 913) - chroot
! Material

!! Time

accuracy vs. precision

Importance of accurate time:
* file timestamps
* tracing events
* security
** certificate validity

Importance of precise time:
* correlating activities between systems

!!! Setting the system date
 - {{Command{tzselect}}} - Select the time zone
 - {{Command{date ~MMDDhhmm&#91;[CC]YY]}}} - set the system date and time
 - Usually not necessary to set the date/time and timezone in a VM.

!!! Network Time Protocol (NTP)
* NTP provides an automated way to keep time in sync and counter clock drift.
* Use a pool of many time servers and the best candidates will be used
* Can maintain to the millisecond 
* Clock strata - Distance from the reference clock
** Stratum 0 - The reference clock.  High precision, high accuracy clocks, such as atomic, GPS, or radio.
** Stratum 1 - Primary time servers.  Systems directly attached to and synchronized with stratum 0 clocks
** Stratum 2 - Secondary time servers.  Systems synchronized to stratum 1 time servers over the network.
** Stratum n+1 up to 15 - Time servers synchronized to a lower stratum clock
** Stratum 16 - An unsynchronized clock.

!!!! NTP Commands:
* {{Command{ntpdate}}} - Client utility.  One time immediate update
* {{Command{ntpd}}} - Background service.  
** Updates slowly in small steps
** Sets and maintains system time in sync with a central point.
** Periodically polls one or more time servers for updates
** May be use an internet based source time server or a local one
** May be configured to provide time synchronization to client systems
** {{Command{ntpstat}}} - show the status of the current ntp service
** {{Command{ntpq}}} - query an ntp server
*** ntpq sub commands:
**** associations
**** peers
*** Tally codes for peers:
**** blank - Unreachable and discarded
**** - - Considered an outlyer and discarded
**** + - Providing data and a candidate for use
**** * - The system peer and providing data

** {{Command{ntpdc}}} - control an ntp server

UDP Reflection attacks against NTP
* monlist command
* ntpdc -n -c monlist
* disable monitor
* add the noquery restriction

!! Logging

* The syslog service is the primary recipient of system-level event log information
** syslog then determines what should be done with that log data based on configuration
*** save it locally, send it to another system, discard it
** Allows for centralized log collection and management
* Some utilities/services log directly to their own files and some use syslog
** Page 343 contains a table of common alternate log file locations
* syslog events are written to the domain socket /dev/log 
** sockets provide inter-process communication via the filesystem
** Processes either communicate via open network ports or these socket files
* log events contain the timestamp, type, severity, and details
* Most log files are plain text, allowing review or parsing with standard unix CLI tools.

* syslog events consist of pre-defined facility and severity levels
** facility is generally the service that generated the message (auth, cron, ftp, mail) and based on standardized names
*** local0-7 facilities are for customized destinations
*** or the keyword none to disable a particular facility or severity
** severity ranges from emergency to debug
*** When specified, that severity level and greater will be processed
** See the /var/log/messages example in /etc/rsyslog.conf
** see ~SysAdmin page 346 & 347 for a list


Most services can elevate verbosity for debugging

syslog components:
* syslogd - the logging service which receives and processes the log information
** /etc/rsyslog.conf
** /etc/rsyslog.d/
* library routines to submit log messages to syslogd
* logger - userland utility for recording log events from the shell.  Handy for scripting.
** Monitor or debug your automated scripts
** Backups and account processing are good examples
** logger -t $0 -p local5.warning "test message"
* logrotate / newsyslog - rotate logs at a configured time or file size
** Retention issues
** compress or delete old logs according to an archival schedule
** /etc/logrotate.conf
** /etc/logrotate.d/
** Executed by cron

Standard exemptions to syslog:
* wtmp - binary file, view with last command
* lastlog - view with lastlog command
* psacct - process accounting service.  View with lastcomm command
** Not built-in.  Will need to install psacct package and enable psacct service
* Apache logging
* DNS logging

syslog as a network service
* syslog is by default a local service and not bound to a network port
* But can be configured to collect log events from multiple hosts
* Many benefits to central logging:

Kernel boot logging and message buffer
* We need a way to record the kernel events prior to init, before syslog starts and the filesystems are mounted
* The kernel stores this boot information in an internal buffer
* Captured by the system and recorded once it fully loads
* Viewable with the dmesg command
* Also saved to /var/log/dmesg

We have all this log data, now what?

* Logcheck - A utility to mine the log data and send reports
* fail2ban - Scan log files and ban malicious ~IPs
** Perform a regular expression match and add offending ~IPs to a firewall
* Web log data
** [[GoAccess|]]
** [[Logstalgia|]] 

Big data analytics: 
* ELK stack
** Elasticsearch - log searching and data analytics
** Logstash - centralized logging and parsing
** Kibana - data visualization
* Splunk

! Assignment

<<tiddler [[Lab 10 - Time & Logging]]>>

!! Read ~SysAdmin Chapter 17 - DNS.  Stop at 17.11 on page 625.

We will be covering DNS next week and configuring the bind DNS server for use based on the content of your zone files.  Be sure your zone files are complete and be prepared to discuss the material of Chapter 17, especially the different DNS record types and how DNS functions between the root and authoritative name servers.

<<tiddler [[Lab 11 - DNS part 1]]>>

!! Authentication & DNS Server:

We will be setting up an authoritative name server for our //username// sub-domains, beginning with the zone files you will create with Lab 9.  Additional configuration will be completed in class next week and we will then bring the DNS servers online. and will be authoritative slaves for your zones.

! Material

!! DNS - Chapter 17

!!! Host names and some history

Hosts file:  {{File{/etc/hosts}}}
 - {{File{/etc/nsswitch.conf}}} query order

!!! DNS - Domain Name System

A distributed and hierarchical database
* must be robust.  function of the internet relies on this
* must be distributed
** different groups responsible for different segments of the data
** if one node goes down the rest of the global network is not impacted
* must be efficient
** LOTS of requests per second
** caching
*** cached responses saved for TTL seconds (time to live)
*** change to low TTL before major updates

!!! Delegation

* root servers  (.)
* Top level domain (TLD):  ccTLD, gTLD, sTLD
** ccTLD:  Country code TLD.  eg:  us, de, cn
** gTLD: Generic TLD.  General purpose.  eg: net, org, com
*** New gTLDs:  Expanding further beyond the original net, com, org:
** sTLD: Sponsored TLD.  Has a sponsor representing a specific group.  eg:  .xxx, .travel, .jobs
** Policy set by the Internet Corporation for Assigned Names and Numbers ([[ICANN|]])
** Lists maintained at the Internet Assigned Numbers Authority ([[IANA|]])
* Domain ownership maintained by central registry operators
** com & net: ~VeriSign
** org: Public Interest Registry
** edu: Educause
** us:  Neustar
** info: Afilias
** arpa: IANA
* Domain sale contracted out to commercial registrars
** Various registrars sell second-level domains.  eg:  Godaddy, enom,, etc.
** The Authoritative name servers for a domain are stored with the TLD's central registry
** whois
* sub-domains
** each domain can delegate authority for sub domains to other servers
** Allows a domain owner to create their own sub-domains
*** edu -> sunyit -> cs
*** -> your domain
* Glue Records

!!! Representation

Fully Qualified domain name (FQDN)
* Similar to an absolute path in the filesystem
* Instead its read right to left
* First is root, the .
* Next the tld (com, edu, org, etc)
* Next the second-level domain
* Sub domains or host names would follow.
* Example:  
* Client tools will append the trailing ''.'' if you leave it out but its use in your DNS zone file matters.

Use the whois tool to obtain domain information.
yum provides '*/whois'

!!Authoritative name server
* Contains the data for a particular zone
* Derived from chaining of NS records starting with the root servers down to the published name servers for a domain
** The NS records identify the authoritative servers and delegate subdomains
* There is typically a master and one or more slaves
** RFC best practices require at least 2 authoritative name servers per domain
* Guaranteed to be up to date.  The data is coming from the source and not cached

dig +trace
dig +trace
 - notice the aa flag

!!! Zone transfer
* Keeps authoritative DNS servers in sync
* We want to have multiple servers per zone, ideally distributed across networks.
* Triggered automatically when master is updated or based on a timeframe in the SOA record
* Typically restricted to systems authorized by an ACL (access control list)
* Our pyramid topology
** ns0 setup - top server which doesn't allow queries from end users distributes zones to lower servers that handle client requests
** especially useful for protecting records and security keys
** and ensuring availability and integrity of the data

!! Non-authoritative
* caching name servers
** cache records for the TTL value
** dig
** dump the cache - rndc dumpdb
** cache snooping
** analyze the cache to see if malware is on your network
* data retained in the cache might be a little stale

off campus:
 - now using local name server
 - notice lack of aa flag

!! Recursive vs non-recursive 
* non-recursive : I don't have that data, but you can look over there
** required for core nameservers to offload lookups to other servers (requires less resources)

* recursive : I don't have that data, but let me find it for you
** Performs queries on behalf of clients on the network  (Your ISP may have one)
** pro - data is stored in the cache for faster future lookups
** con - ~DDoS amplification attacks
     Up to 70:1 attack ratio (60 bytes for the request, 4000 for the response)
     spamhaus attack - 100gbps
     demo : dig any
                dig +edns=0 +bufsize=4096 any
     DNS traffic is UDP, fire and forget, easy to spoof
     Like open mail relays - have to close down open recursive servers now that they're being actively exploited
     dig +short txt 
** mix - allow recursion for local hosts, but not for remote ones


!! Hints file
*Store and serve IP addresses for root servers on local DNS server

!!! Querying DNS

* nslookup
* host
* dig [record_type] record [@server]
** dig -x for reverse queries
* drill

* dig
* dig

!! Creating Zones

DNS records are grouped into zones on the actual authoritative name servers
each zone contains resource records of various record types
*lines in the zone files are our records
*There are two types of zones, forward and reverse
**forward: host name to IP address
**reverse: IP address to host name

!! Primary Resource Record types

!!! Configuring Bind

Lets stand up our authoritative name server

on auth box: yum install bind-chroot bind-utils
* bind runs chrooted to protect the system

Edit its config file, {{File{/etc/named.conf}}}

This block should be added within the options section of named.conf:

	listen-on port 53 { any; };

	allow-query     { dognet; };
	allow-recursion { cs407; };
        forwarders {; };


!!! Access control lists:

Add access control lists to the top of the file.  This ~ACLs will limit who can query your name server.

acl "dognet" {;;;;        

acl "cs407" {;


!!! Forwarders:
The name server will forward any query it can't answer locally (from authoritative zone data or from cache) to the forwarder.
Forwarders are queried in the listed order until an answer is received

!!! Starting bind

Start the named service
Set it to also start at system boot

!!! Defining zones:

Lets put our zone definitions near the bottom of named.conf:

!!!! Forward zone:
zone "" {
        type master;
        file "/etc/named/master/";

 - Create the forward zone file
 - Restart bind to cause it to take effect
 - Test your DNS records with dig

!!! Allowing zone transfers to the slave

on your auth vm, add a new ACL to the top of named.conf:
acl "slaves" {;		// allow the secondary authoritative name server to perform zone transfers
	10.103.36.x;		// allow your auth system to preform zone transfers.  Replace x with the IP address of your auth VM;		// A slave for your DNS server;		// A slave for your DNS server

and add this statement to the options section:
	allow-transfer  { slaves; };

Restart bind to reload the configuration.

!!! Configure the slave

On (the slave managed by the CS Dept), I need to add a configuration block similar to the following to named.conf for each student network in the class.  This will configure that server to become a slave for your zones:
zone "" {
        type slave;
        file "slave/";
        masters {; };

!!! DNS client configuration

Now modify resolv.conf to add our new nameserver and expand the search domains
* We want to query our nameserver first and the dognet ns4 second
* We want to search our domain first

You can access your ~VMs by host name from anywhere within the CS network once the CS nameserver is aware of your zones.

!!! Reverse zone

Add this zone declaration to the end of your {{File{named.conf}}}
zone "" in {
        type master;
        file "/etc/named/master/";

- restart named

!! Misc DNS topics

Don't forget to update your serial number!
- Notifications are broadcast to slave NS upon serial increment
- Records may be stale if you forget to increment serial

rndc command vs. restarting the service

!! Additional reading
 - kaminsky DNS bug
 - get familiar with the dig command
 - EXPOSURE: Finding Malicious Domains Using Passive DNS Analysis -


! Assignment

!! Continue reading ~SysAdmin Chapter 17 - DNS

Beginning at 17.12 on page 638
Stop at 17.14 on page 667
Focus on DNSSEC
Table 17.16 on page 675 contains useful rndc commands
The "Debugging with dig" section starting on page 677 is worthwhile.

<<tiddler [[Lab 12 - Bind config and zones]]>>

<<tiddler [[Lab 13 - DNS Security Extensions]]>>


!!Useful reading:

*[[DNS for Rocket Scientists|]]
*Open Resolvers for network amplification attacks (~DDoS)

! References:
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class="editor">Title</div><div class='editor' macro='edit title'></div>
<div class="editor">Tags</div><div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
[[Final Exam|CS407Final.pdf]]



|  ! | !Missing | !Lab | !L0 | !L1 | !L2 | !L3 | | !L5 | | | !L8 | !L9 | !L10 | !L11 | !L12 | !L13 | !L14 | !L15 | !L16 | !L17 | !L18 | !L19 | | !L21 | !L22 | | !L24 | !L25 | | !L27 | !L28 | !L29 | !L30 | !L31 | | !L33 | !L34 |
| !ID | !Labs | !Grade | !10 | !10 | !10 | !10 | | !10 | | | !10 | !10 | !10 | !10 | !10 | !10 | !10 | !10 | !10 | !10 | !10 | !10 | | !10 | !10 | | !10 | !10 | | !10 | !10 | !10 | !10 | !10 | | !10 | !10 |
| 0264 | 0 | B | 10 | 5 | 10 | 10 | | 8 | | | 9 | 10 | 10 | 9 | 10 | 7 | 10 | 10 | 7 | 10 | 8 | 6 | | 8 | 10 | | 7 | 10 | | 7 | 7 | 10 | 7 | 10 | | 8 | 8 |
| 0620 | 1 | B+ | 10 | 8 | 10 | 10 | | 6 | | | 9 | 10 | 10 | 10 | 10 | 8 | 10 | 8 | 7 | 10 | 10 | 10 | | 10 | 10 | | 10 |  | | 8 | 8 | 10 | 10 | 10 | | 8 | 6 |
| 1096 | 0 | A | 10 | 8 | 10 | 10 | | 9 | | | 10 | 10 | 10 | 9 | 10 | 9 | 10 | 9 | 10 | 10 | 10 | 10 | | 10 | 10 | | 10 | 10 | | 10 | 10 | 10 | 10 | 10 | | 8 | 9 |
| 1516 | 2 | B- | 10 | 9 | 10 | 10 | | 9 | | | 10 | 10 | 10 | 10 | 10 | 9 | 7 | 10 | 7 | 10 | 10 | 7 | | 8 | 10 | | 7 | 10 | | 8 | 8 |  | 10 |  | | 8 | 7 |
| 2562 | 6 | D | 10 | 8 | 10 | 10 | | 9 | | | 9 | 10 | 10 | 6 | 10 | 6 | 6 | 7 | 6 | 10 | 7 | 5 | | 10 | 8 | |  | 10 | | 7 |  |  |  |  | |  | 6 |
| 3757 | 0 | A- | 10 | 8 | 10 | 10 | | 10 | | | 10 | 10 | 10 | 10 | 9 | 7 | 7 | 10 | 10 | 10 | 10 | 7 | | 10 |  | | 9 | 10 | | 10 | 10 | 10 | 9 | 10 | | 8 | 10 |
| 5275 | 4 | C- | 8 | 8 | 10 | 10 | | 5 | | | 10 | 10 | 10 | 9 | 10 |  | 7 | 7 |  | 10 | 7 | 10 | | 8 | 8 | | 8 |  | | 7 | 7 | 10 |  | 10 | | 8 | 7 |
| 5302 | 2 | A- | 10 | 8 | 10 | 10 | | 10 | | | 10 | 10 | 10 | 9 | 10 | 8 | 10 | 10 | 10 | 10 | 10 | 10 | | 10 | 10 | |  | 10 | | 8 | 10 | 10 |  | 10 | | 10 | 10 |
| 6896 | 0 | A | 10 | 9 | 10 | 10 | | 10 | | | 10 | 10 | 10 | 10 | 10 | 9 | 10 | 10 | 10 | 10 | 10 | 10 | | 8 | 10 | | 10 | 10 | | 10 | 10 | 10 | 10 | 10 | | 9 | 10 |
| 7161 | 0 | A | 10 | 9 | 10 | 10 | | 10 | | | 10 | 10 | 10 | 10 | 10 | 10 | 10 | 10 | 10 | 10 | 10 | 7 | | 10 | 10 | | 10 | 10 | | 10 | 10 | 10 | 10 | 10 | | 9 | 10 |
| 7410 | 4 | C | 8 | 7 | 10 | 10 | | 8 | | | 10 | 10 | 10 | 9 | 10 | 7 | 10 | 8 |  | 10 | 7 | 7 | | 10 | 10 | | 7 |  | | 8 |  | 10 |  | 10 | | 7 | 6 |
| 9733 | 3 | B | 10 | 9 | 10 | 10 | | 10 | | | 10 | 10 | 10 | 10 | 10 | 8 | 10 | 10 |  | 10 | 10 | 7 | | 10 | 10 | | 10 | 10 | | 10 | 10 | 10 |  |  | | 10 | 6 |

!!See grading note at bottom

!!! {{Remove{Project and final grades will be finished Friday}}}

!!@@display:block;text-align:center;ID = last 4 digits of U number@@

{{{*}}} Current letter grade displayed does not include extra credit awarded for class participation.  Tests taken later in the semester will influence this grade more then labs completed in the beginning of the semester.  A poor grade early on can be significantly improved with good test scores and class participation.  A poor grade late in the semester can be improved by completing missed labs.  See me for details or for a projected final course grade.

!CS 407 Course Notes

[[Day 0]] W 1/21 - Administrative Tasks & course intro
[[Day 1]] W 1/21 - Unix refresher
[[Day 2]] M 1/26 - Basic networking & Unix refresher part 2
[[Day 3]] W 1/28 -  System Basics - Starting and Stopping, init & run levels, layout of the operating system, system configuration (/etc/ files).
M 2/2 - Snow day
[[Day 4]] W 2/4 - Unix review, lab 1 review, working with SSH & screen
[[Day 5]] M 2/9 - Documentation, Expanding our systems:  Working with rpm & yum, installing software from package and source
[[Day 6]] W 2/11 - UNIX command line and manipulating the shell environment
[[Day 7]] M 2/16 - Proxies, tunnels, and Web services
[[Day 8]] W 2/18 - Time & Logging
[[Day 9]] M 2/23 - DNS Part 1
[[Day 10]] W 2/25 - DNS Part 2
[[Day 11]] M 3/2 - Access control and user management
[[Day 12]] W 3/4 - Storage, standard filesystems, and LVM
3/9 - 3/13 - Spring Break
[[Day 13]] M 3/16 - NFS, file sharing and different file system types
[[Day 14]] W 3/18 - Crypto & securing communication
[[Day 15]] M 3/23 - ~OpenLDAP & centralized authentication
[[Day 16]] W 3/25 - ~OpenLDAP part 2
[[Day 17]] M 3/30 - Scheduling Tasks, Backups, & disaster recovery
[[Day 18]] W 4/1 - network / system enumeration and security tools
[[Day 19]] M 4/6 - Host based firewalls  (Last day to withdraw)
[[Day 20]] W 4/8 - Patching and staying up to date
M 4/13 - Class Canceled
[[Day 21]] W 4/15 - Additional filesystem topics
[[Day 22]] M 4/20 - Performance monitoring
[[Day 23]] W 4/22 - Hack box review / The Kernel / Email server setup
[[Day 24]] M 4/27 - Email
[[Day 25|Final Exam]] W 4/29 - [[Final Exam]]

[[Projects]] M 5/4 - Project Presentations

[[Day 25]] W 4/29 - Email
[[Day 26]] M 4/20 - Drivers and the kernel 

!!!&nbsp;Agendas for days in italics are tentative
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also HorizontalMainMenu and PageTemplate.

#topMenu br {display:none; }
#topMenu { background: #39a; }
#topMenu { float: left; }
#topMenu { width: 90%; }
#topMenu { padding: 2px 0 2px 0; }
#topMenu .button,  #topMenu .tiddlyLink { padding-left:1em; padding-right:1em; color:white; font-size:115%;}
#displayArea { margin: 1em 15.7em 0em 1em; }

#rightMenu {
   float: right;
   background: #39a;
   width: 10%;
   padding: 2px 0 2px 0;
#rightMenu .button,  #rightMenu .tiddlyLink { padding-left:1em; padding-right:1em; color:white; font-size:115%;}

/* just in case want some QuickOpenTags in your topMenu */
#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }
#topMenu .quickopentag .tiddlyLink { padding-right:1px; }
#topMenu .quickopentag .button { padding-left:1px; border:0px; }

<html><center><img src="" alt="Index Card"></center></html>

!![[Lab 00 - Connect to fang]]
Assigned [[Day 1]], Due Jan 26

*SSH into fang
*Access your CS email with {{Command{pine}}}
*Send me an email so I know everyone can log in and access your email.  __Email subject: ~CS407/~NCS522__
*I will be using your CS email address (//username// if I need to contact you.  Set up email forwarding if you will not be checking your CS email.
**Create a file named .forward in your home directory on fang that contains only the forwarding email address.
**Verify email forwarding with the finger command.  {{Command{finger //username//}}}
!![[Lab 01 - UNIX Refresher]]
Assigned [[Day 1]], Due Jan 26

The attached [[Lab 1 PDF|labs/Lab1.pdf]] is due start of class.  

Submission Instructions:
(I do not accept paper)

* Create the directory ~/cs407/labs/
* Set permissions on this directory so no other users on the system can access it.
* Record your answers in the PDF form fields and save the completed PDF in the directory above.  Name the file cs407-lab1-//username//.pdf
* Also bring a printed copy of the PDF to class.

  ** Be sure to use Acrobat reader. Other PDF readers may not properly save the form field contents.
!![[Lab 02|Lab 02 - Bring VMs Online]] - Bring test and www online
Assigned [[Day 2]], Due Jan 28

Ensure your test and web ~VMs are online.  Use the hostname www and second IP address in your range for your web server.
!![[Lab 03 - Install man]]
Assigned [[Day 3]], Due Feb 2

Use yum to install the man utility on your test and www ~VMs
!![[Lab 04 - VM updates & software installation]]
Assigned [[Day 5]], Due Feb 11

!!! On both ~VMs:
* Update the OS and currently installed software
* Install the following packages:  man wget nc telnet bind-utils openssh-clients rsync

These packages will also need to be installed on all future ~VMs
!![[Lab 05 - Web Server]]
Assigned [[Day 5]], Due Feb 16

Finish installing php and mySQL if we didn't have time to in class.  See notes above.

Become familiar with apache and its configuration.  Check out the config files within {{File{/opt/work/apache/conf/}}} and the different binaries within {{File{/opt/work/apache/bin/}}}

Move your Apache ~DocumentRoot from {{File{/opt/work/apache_2.2.29/htdocs}}} to {{File{/opt/work/htdocs}}}
* Move the directory and update the apache configuration file statement which points to it
(you may need to change this path in more then one location within the apache config)

Start the mySQL service and configure the system for it to start on boot

Create a mySQL database and user account for the wiki to use.
* Connect to mySQL with {{Command{mysql -u root -p mysql}}}
* Enter the following:
CREATE USER 'wiki_user'@'localhost' IDENTIFIED BY 'wiki_pass';
CREATE USER 'wiki_user'@'' IDENTIFIED BY 'wiki_pass';
create database wiki;
GRANT select, insert, update, delete, create, index ON wiki.* TO 'wiki_user'@'localhost';
flush privileges;
Change the username ''wiki_user'' and password ''wiki_pass'' to whatever you would like.

By default the mySQL server root account does not have a password set.  Secure the mySQL root account and ensure a password is set.  Research, record, and apply the steps necessary to accomplish this.  The required step should be added to your lab wiki once its online.

Be sure to record your steps in your changelog!

Preview:  We will be setting up [[MediaWiki|]] next Monday, unpacking it to /opt/work/htdocs/ and renaming the base directory from ''mediawiki-1.24.1'' to ''wiki''
!![[Lab 06 - Customize your environment]]
Assigned [[Day 6]]

Experiment with the various shell configuration files and setting to customize your environment to your taste.  This lab will not be reviewed or graded, though being familiar with the environment will be helpful for the final exam.
!![[Lab 07 - Lab return shell script]]
Assigned [[Day 6]], Due 2/18

Write the shell script I will use to return annotated and graded lab pdf files.  Save it to ~/cs407/labs/cs407-lab7-//username//.sh

Labs I have collected from the class are copied to my home directory within ~merantn/cs407/labs/submitted/
Labs annotated and ready to be returned are then saved in ~merantn/cs407/labs/graded/
Ownership of these graded files needs to be changed so their owner can review my notes.

* Write a shell script that will change ownership of all lab files saved in the graded directory to their author.  
** Extract the username from the name of the file and use it as an argument to the chown command.
* For good measure, also set the permissions on the file to be readable only by the owner. (In case I forgot to)

Labs will always follow the format cs407-lab#-username.ext
* The lab number will contain numbers and may end with a letter
* The file extension (ext) is variable.  It may be pdf, txt, or sh.

Material which may be helpful:
* ~SysAdmin section 2.2
* My ~CS307 class notes:  [[Shell scripting 1|]]
* A shell scripting reference I like to use:
* Hint:  A for loop may make this easier.  Use basic unix commands within the loop.
!![[Lab 08 - Set up MediaWiki]]
Assigned [[Day 7]], Due Feb 18

Finish what we didn't get to in class today.  Make sure your web server is fully online with php support and ~MediaWiki available.

Install [[MediaWiki|]] and customize it to your tastes.
* Download the source tarball
* Extract its contents to /opt/work/htdocs/
* Rename the extracted directory to ''wiki''
* The final URL for your wiki will be
* You can access it by IP address until DNS is online:  http://your_IP/wiki/
!![[Lab 09 - Bring auth VM online]]
Assigned [[Day 7]], Due Feb 18

Bring your new auth VM online:
* Configure networking - use the third IP address in your range
* Set the host name to auth
* Add appropriate entries to the hosts file
* Install additional software:
** Standard packages, as previously discussed and recorded in your class notes
!! [[Lab 10 - Time & Logging]]
Assigned [[Feb 18|Day 8]], Due Feb 23

!!! Hosts file:

Create the following records in the {{File{hosts}}} file on your web and auth ~VMs:
* host name ''ntp'' point to your auth VM
* host name ''loghost'' point to your auth VM

!!! NTP:

Install ntpd and ntpdate on all ~VMs

auth:  Configure ntpd (/etc/ntp.conf) server:
* By default the ntp configuration allows global access to the NTP server.  
** Disable the first two restrict directives
** Insert:  restrict default ignore
* Allow your block of 8 IP addresses to communicate with the NTP service running on your auth VM
** Add the appropriate restrict directives
** Be sure to include nopeer & noquery 
* Insert: disable monitor
* Synchronize time from the CS ntp servers instead of the ~CentOS servers
** Add restrict directives to allow these two hosts full access
* Allow nagios server:
** restrict nomodify notrap

www:  Configure ntpd client:
* Synchronize time from your ntp server instead of the ~CentOS servers
** ntp.//username//

All ~VMs:
Set ntpd and ntpdate to start on boot on all ~VMs
Start the ntpd service now on all ~VMs

My Configs (click to expand):
* Be sure to change host names and IP addresses appropriately:
* +++[Server]
auth# grep -v ^# /etc/ntp.conf | uniq
driftfile /var/lib/ntp/drift

restrict default ignore
restrict -6 default ignore

restrict -6 ::1

restrict mask nomodify notrap nopeer noquery
# Allow nagios server to check status of NTP
restrict nomodify notrap

server iburst
server iburst
restrict notrap nopeer noquery
restrict notrap nopeer noquery

disable monitor

includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys

* +++[Client]
www# grep -v ^# /etc/ntp.conf | uniq
driftfile /var/lib/ntp/drift

restrict default ignore
restrict -6 default ignore

restrict -6 ::1

restrict notrap nopeer noquery

includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys

!!! syslog:

* configure syslog to receive log information from other hosts

* configure syslog to also send log information to the auth VM
!! [[Lab 11 - DNS part 1]]
Assigned [[Day 5]], Due Sep 15

Complete [[Lab11|labs/lab11.pdf]].  Save it to ~cs407/labs/cs407-lab11-//username//.pdf

Bring new auth VM online:
* Hostname = auth
* Use the third IP address in your range

Install additional software:
* Standard packages, as previously discussed and recorded in your class notes
* DNS server software.  The package is bind-chroot

Build forward and reverse DNS zone files for your sub-domain and three ~VMs
 - Your forward zone file should be named /etc/named/master/
 - Your reverse zone file should be named /etc/named/master/
 - Replace username with your actual campus username
 - Store these files in {{File{/tmp/}}} on your auth VM.  We will move them next week.

You will need to (minimally) understand SOA, NS, A, CNAME and PTR records.
 - create A and PTR records for your hosts (so far we have 3 ~VMs: test, web, and auth)
 - create CNAME records so the hostnames ''directory'', ''ntp'', and ''loghost'' point to auth
 - create an additional A record so the host ''ns1'' also resolves to your auth VM
 - The hosts ns1.//username// and will be authoritative for your zones.  Create appropriate NS records.

!![[Lab 12 - Bind config and zones]]
Assigned [[Day 9]], Due Feb 25

Ensure the DNS server on your auth VM is fully online and responding to queries
* Configure bind
** Apply configuration settings noted above
** You should also have:
*** NS records for your primary and slave DNS servers
*** A and PTR records for each of your hosts (so far we have 3 ~VMs: test, web, and auth)
*** CNAME records for host name __directory__, __ntp__, and __loghost__ pointing to your auth VM
* Start the service
* Set it to start on system startup
* Adjust the resolv.conf file so your ~VMs use your name server and add your domain to the beginning of the search string
!! [[Lab 13 - DNS Security Extensions]]
Assigned [[Day 9]], Due Fri, March 6

- Research DNS Security extensions and prepare a writeup from a cryptographic and implementation perspective.
- Explain how DNSSEC works and what we have to do to implement it

Be sure to include:
* How trust and security is established and verified
* Pros and cons, issues addressed and issues created
* How to implement in bind

Save your writeup to your home directory as ~/cs407/labs/cs407-lab13-//username//.pdf

Once you have a firm understanding of DNSSEC and how to implement it, secure your zones and prove effectiveness.
- Include this proof in your writeup

Not all ISP name servers will verify DNSSEC
 - time warner doesn't
 - you may have to use
!! [[Lab 14 - Additional DNS records]]
Assigned [[Day 10]], Due Mar 2

!!! Reverse zone

Ensure you have a valid reverse zone for all of your hosts
Remove the NS record for {{Host{}}}

!!! Zone apex

Create an A record so your zone apex resolves to your web server

!!! SSH Fingerprints in DNS

Research and implement SSHFP records for all of your hosts.  Be prepared to discuss their pros and cons and whether our current implementation increases the security of your hosts.
!! [[Lab 15 - VM Lockdown - Secure your VMs]]
Assigned [[Day 11]], Due Mar 4

!!! Add user accounts to all ~VMs

Add a UID 0 account for me on your ~VMs
* Set user name to toor
* Use this hash: 

Add a local admin account to your ~VMs
* Set user name to admin
* UID = 1000
* GID = 100
* Set a valid password
* Create a home directory
* Copy my SSH public key (see below) to its {{File{~/.ssh/authorized_keys}}} file
* Copy the SSH public we created on [[Day 4]] to its {{File{~/.ssh/authorized_keys}}} file
* Verify permissions:
** The admin home directory and all files below it must be owned by the admin user and GID 100
** /home/admin and below must not be writable by the group or others for proper SSH function.
* Verify ~SELinux
** ~SELinux must be disabled for SSH public key authentication to function properly
** Edit /etc/selinux/config and change enforcing to disabled on line #7 to disable ~SELinux on system startup
** Execute {{Command{setenforce 0}}} to disable ~SELinux for the current boot

My SSH public key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjDXBhIjaHcNNsNXkWxHmuwnU1+q0mMXSdobP+DP/X/57j9Txne6akT1nN8uF5YrTpRN/pIlKhsPFHVHjdPRzllV4vSBNyU8HWQmhPYjAvMsKGURU7PcQG40gkSe8hWCMRjGt37yj25c9mvb1A9hsC42jGIK5VlzoJPN/e8JRm7vXA7GFfrrutsYItnU3T1AG+B4tv/OyUE+xHkDcrdGPjn8M76mxgkBH1f/CyhOAC0D+ldQ5KXpgBm7P8oKhVDAXXJhoWMmpMjWiYRGVHEIJrnptBK9SznSvwN82K3H3jITuGlbtZOek9MBXPY5hRPb7PC6j6w5npF0Q/ZiEOmnIb merantn@cs407-2

!!! Disable direct root login via SSH on all ~VMs

* Adjust the sshd configuration to disable direct root logins.  All users must first login as a regular account and then elevate privileges.  
* Adjust PAM to require wheel group membership in order to su to root
* Don't forget to add the admin user to the wheel group
!![[Lab 16 - sudo]]:  apache configuration access
Assigned [[Day 11]], Due Friday, Mar 6

We would like to provide the webmaster the ability to update the apache configuration and restart the service on the web server virtual machine without granting full root level access.  The {{Command{sudo}}} and {{Command{sudoedit}}} utilities can be use to accomplish this.

Since we do not yet have a additional users, elevated access to apache will be achieved via the admin user.

Configure {{Command{sudo}}} / {{Command{sudoedit}}} to:
# Grant the admin user the ability to edit the primary apache configuration file
# Grant the admin user the ability to execute apachectl as root.

Be sure you understand why {{Command{sudoedit}}} is used for modifying root-owned files instead of {{Command{sudo}}}
!! [[Lab 17 - Bring the storage server online]]
Assigned [[Day 11]], Due Mar 4

Bring your storage server online:
* Use the fourth IP address in your range
* Use the hostname {{Host{files}}}
* Also install the following packages:  nfs-utils nfs4-acl-tools portmap
* Apply configuration changes made to previous ~VMs
!![[Lab 18 - Fix SSHFP Records]]
Assigned [[Day 12]], Due Mar 16

We discovered a problem with our VM's SSH host keys after analyzing our SSHFP records in DNS.  The security of our SSH communication relies upon unique and secure keys.  It would be possible to decrypt our traffic, potentially divulging credentials or privileged information if these keys are divulged.

Take corrective action on all of your virtual machines to ensure each virtual machine has unique host keys:

# Delete all ssh host keys found in {{File{/etc/ssh/}}}
# Restart the sshd service to regenerate new keys
# Create new SSHFP DNS records and update your zones
!![[Lab 19 - Logical Volume Manager]]
Assigned [[Day 12]], Due Mar 3

Complete [[Lab 19|labs/lab19.pdf]] on the files VM to become familiar with the Linux logical volume manager.

Add additional filesystems to your web server and auth ~VMs as described on the last page of Lab 19
* Save a text file in your ~/cs407/labs/ directory named cs407-lab19-//username//.txt containing all commands used to create the new filesystems on the web and auth ~VMs
* The {{Command{script}}} command may be useful for capturing your command history
!![[Lab 20 - Move apache logs]]
Assigned [[Day 12]], Due Mar 16

We want to utilize the new /var/log/ filesystem on the web VM for the apache log files.  The files will need to be physically relocated to the new filesystem and the apache configuration updated to utilize the new log location.
# Stop apache.  The service must be stopped prior to moving the log files
# Move log files located in {{File{/opt/work/apache/logs/}}} to {{File{/var/log/apache/}}}  (you will need to first create this new directory)
# Update the apache configuration file:
## Open the apache configuration file in a text editor
## Search for the string ''logs'' throughout
## Replace the relative path specifying the log file's location with an absolute path of the file's new location
## You may have to do this for multiple occurrences throughout the file
# Start apache
# Verify that new log information is appearing in the log files
## Change to the new apache log directory
## Run {{Command{tail -f access_log}}}
## Access your web server in your browser
## Ensure log entries are being added
## ~CTRL-C to terminate the tail command
!![[Lab 21 - NFS]]
Assigned [[Day 13]], Due Mar 23

~SysAdmin Chapter 18 will cover NFS in detail.

Refer to the steps above within the NFS section on this page to:
# Configure your file storage server to provide NFS access to /home and /opt/backups
# Configure your web server to mount these filesystem
!![[Lab 22 - Monitoring disk usage with Nagios]]
Assigned [[Day 13]], Due Mar 20

Nagios checks are performed through a series of plugins.  Nagios plugins are shell scripts or binary executables which perform their specific check and return their results to the Nagios service.

Currently the majority of our nagios checks are for services running on our ~VMs.  The Nagios plugins interact with these services in a normal fashion and records its findings for display on the web interface.  Occasionally it is necessary to examine a system internally, beyond the reach of our standard external plugins.  The Nagios Remote Plugin Executor (NRPE) is a service which can be run on a system being monitored to provide a central Nagios server the ability to execute internal plugins and examine the target system from the inside.  The Nagios server will communicate with NRPE and request it run a local plugin residing on the target system.  NRPE will then return the results of that plugin to the Nagios monitoring service.  

Certain checks, such as those examining the amount of free space available on a system, can only be performed via NRPE and a plugin residing on the system being checked.  Monitoring the amount of free space in your log and home directory partitions is of special importance in order to prevent log information loss or user data loss.

Install NRPE and the necessary nagios plugin on each of your production ~VMs.  Configure NRPE to grant our Nagios server permission to access it and configure the disk check plugin to monitor the /var/log and /home filesystems.

!!! 1. Install the EPEL repository

Install the Extra Packages for Enterprise Linux (EPEL) yum repository.  The extra Nagios utilities and plugins are not available via the standard yum repo that ships with ~CentOS.

{{Command{yum install epel-release}}}

!!! 2. Install the nrpe service and nagios disk check plugin via yum:

{{Command{yum install nrpe nagios-plugins-disk}}}

!!! 3. Edit the {{File{/etc/nagios/nrpe.cfg}}} config file:

Search for the ''allowed_hosts'' configuration directive and grant the local system and the nagios server permission to access it:

Add these two lines to the end of the command definitions (towards the bottom), creating disk check commands for /var/log and /home.  The nagios server will execute these configured commands via the NRPE service.
command[check_disk_log]=/usr/lib64/nagios/plugins/check_disk -w 15% -c 8% -p /var/log
command[check_disk_home]=/usr/lib64/nagios/plugins/check_disk -w 15% -c 8% -p /home

The disk check command for /home is only necessary on the files VM, though it may be included in the config file on all ~VMs for consistency.  

!!! 4. Start the service:

Start now:
 - {{Command{service nrpe start}}}
Start on boot:
- {{Command{chkconfig nrpe on}}}
 - {{Command{chkconfig | grep nrpe}}}

!!! 5. Install the NRPE Nagios plugin

This is the plugin used by the Nagios server to call remote commands via NRPE.  Normally this plugin is only installed on the nagios server.  We're installing in on our VMs for testing.

{{Command{yum install nagios-plugins-nrpe}}}

!!! 6.  Test

Execute the nagios plugin to test your NRPE instance.  The string returned is what would be reported back to Nagios and what will be displayed on the Nagios web interface.

{{Command{/usr/lib64/nagios/plugins/check_nrpe  -H -c check_disk_log}}}
{{Command{/usr/lib64/nagios/plugins/check_nrpe  -H -c check_disk_home}}}
!! [[Lab 23 - Filesystem Options]]
Assigned [[Day 13]], Due Mar 20

Adding basic filesystem options to the /tmp and /home filesystems is an easy way to improve system security without negatively impacting your users.  

On all ~VMs, enable the noexec option to /tmp/ and the nosuid option to /home.

1) Add the appropriate options to the mount options column in the {{File{/etc/fstab}}} file.  This will ensure proper options are set on boot

/dev/mapper/VolGroup-lv_tmp  /tmp              ext4    defaults,noexec  1 1
/dev/Storage/home       /home                  ext4    defaults,nosuid  1 1
/dev/Storage/backups    /opt/backups           ext4    defaults         1 1
/dev/Storage/log        /var/log               ext4    defaults         1 1

2) Remount the filesystems to set the new options:

mount -o remount,noexec /tmp
mount -o remount,nosuid /home

3) Verify with the {{Command{mount}}} command:

# mount
[ ... ]
/dev/mapper/VolGroup-lv_tmp on /tmp type ext4 (rw,noexec)
/dev/mapper/Storage-home on /home type ext4 (rw,nosuid)

!! [[Lab 24 - hack1 break-in]]
Assigned [[Day 13]], Due Mar 23

Access hack1 for a little CTF:
* It's running on the last IP address of your range
** Create an A record so host name hack1 points to this IP address
* The ultimate objective is to root the box
* Flags to capture:
** /home/paco/flag1.txt
** /tmp/flag2.txt
** /root/flag3.txt

What's the highest number flag you can access?

This lab will draw on material covered in [[Day 13]] (NFS), [[Day 11]] (Access control and elevating privileges), and [[Day 4]] (SSH)

Record your steps and the contents of the flags to your ~DogNET home dir ~/cs407/labs/cs407-lab24-//username//.txt
 - File line #1 is your name
 - File line #2 is the output of the highest flag you were able to obtain
 - Then list your steps on the following lines

Be sure to chmod the file 600
!![[Lab 25 - SSL Certificates]]
Assigned [[Day 14]], Due March 23

You will need to have certificates created for your {{Host{www}}} and {{Host{auth}}} ~VMs before next class.

Run the commands presented above (or textbook section 23.4) on your www and auth ~VMs, saving any generated files as {www,directory}.//username//.{key,csr} within {{File{/opt/work/certs/}}}.
 - The SSL certificate for the authentication server will be used by LDAP, the central authentication store we will be configuring next week.  LDAP will be accessed via the CNAME record {{Host{directory.//username//}}}
Copy your Certificate Signing Request files to your ~DogNET home directory within {{File{~/cs407/certs/}}}
 - Email me when the csr files are there
 - I will use the CA certificate I hold and CA commands above to generate your certs.
 - Then email you when they are ready.

The auth VM SSL key must not have a passphrase associated with it.  Omit the -des3 option from the openssl command string when generating its key and you will not be prompted for a passphrase.
When creating the certificate signing requests, be sure to use a FQDN in the common name field.
 - Use {{Host{www.//username//}}} for the web server
 - Use {{Host{directory.//username//}}} for the auth server.
I will play the role of the certificate authority, generate certificates and save them to my {{File{~/cs407/certs/}}} directory.

!!! Enable SSL Support for apache
Configure apache for SSL support
* Configure {{File{extra/httpd-ssl.conf}}} file
** Set host name
** Set key and certificate path
** Change log locations
* Enable the Include statement in the {{File{apache conf}}}
* Restart apache (stop and start)
** {{Command{./apachectl restart}}} is not sufficient to activate large configuration changes such as adding SSL

Test: {{Command{openssl s_client -connect www.//username// -showcerts}}}
!! [[Lab 26 - Install OpenLDAP]]
Assigned [[Day 14]], Due March 23

This ''must'' be completed prior to our next class

!!! On auth VM:

!!!! LVM:
Ensure Storage volume group exists and contains:
* work : 256mb mirrored
* ext4 filesystems the logical volume
* Mounted to /opt/work 
* Added to /etc/fstab for mounting on boot
From [[Lab 19 - Logical Volume Manager]]

!!!! NFS:
Ensure /home/ is NFS mounted from the files VM 
and an appropriate entry exists in /etc/fstab to mount /home on boot
From [[Lab 21 - NFS]]

!!!! DNS:
Ensure the directory CNAME record exists and points to the auth server
From [[Lab 11 - DNS part 1]]

!!!! SSL:
Ensure your SSL key has been created and saved within auth:/opt/work/certs/
Ensure your certificate signing request (CSR) file was saved to fang:~/cs407/certs/
Copy your certificate file (.crt) from fang:~merantn/cs407/certs/ to auth:/opt/work/certs/
From [[Lab 25 - SSL Certificates]]

!!!! Create a RAM disk scratch space for your sources

Downloading and compiling from source can consume a large amount of disk space, especially multiplied by the number of students in our class.  Currently RAM is the abundant resource in our virtualization servers and disk space is at a premium.  Recall our disk storage lecture and the discussion of thin provisioning and expanding virtual disk files.

Creating a RAM-backed filesystem can provide fast storage without consuming actual disk space on the server, thus helping to reduce our disk usage problem.  

Create a mount point:  {{Command{mkdir -p /opt/src}}}
Create the tmpfs filesystem for our compile scratch space:  {{Command{mount -t tmpfs -o size=128m tmpfs /opt/src}}}
The amount of available RAM will be reduced by the size specified.  It is important not to set the size larger then the amount of total RAM or starve your system for resources.
We will unmount the /opt/src filesystem after ~OpenLDAP is installed and make the RAM available to the system.

!!!! Install ~OpenLDAP:
Download and install ~OpenLDAP from source
* See
* Install dependencies with yum:  wget, gcc, make, openssl-devel, db4, db4-devel
* Download latest version of ~OpenLDAP sources to your RAM disk {{File{/opt/src/}}} directory
* Unpack the tarball
* Run the following configure script
** You may need to replace the version numbers listed below with the current ~OpenLDAP version number
./configure \
--prefix=/opt/work/openldap-2.4.40 \
--sysconfdir=/opt/work/openldap-2.4.40/etc \
--with-threads=posix  \
--with-tls=openssl  \
--disable-dependency-tracking  \
--enable-dynamic  \
--without-fetch  \
--without-cyrus-sasl  \
--enable-crypt  \
--enable-ldap=mod  \
--enable-meta=mod  \
--enable-rewrite  \
--enable-null=mod  \
--enable-monitor=mod  \
--enable-seqmod=yes  \
--enable-syncprov=yes  \
--enable-bdb=mod  \
--enable-hdb=mod  \
--enable-mdb=no  \
--enable-aci \
* Build dependencies, compile application, and install

!!! Wrap-up
* Unmount the /opt/src tmpfs filesystem
* Create the symbolic link {{File{/opt/work/openldap}}} pointing to the ~OpenLDAP installation directory.
* We will discuss central authentication and configure ~OpenLDAP for use next class
!! [[Lab 27 - OpenLDAP Server]]
Assigned [[Day 14]], Due Mar 25

Configure and bring the ~OpenLDAP service online on your auth VM

!!! Basic Configuration

As discussed in [[Day 15]], bring the ~OpenLDAP server online and prepare it for client authentication.
* Remove the version string from the slapd.conf file
* Add the additional schemas
* Set the suffix, rootdn, and rootpw values
* Secure the config file and set proper ownership
* Create the ldap service account
* Set proper permissions on the data directory
* Set slapd to start on boot
* Add user accounts for yourself and merantn
We'll do these three on Wednesday:
* Secure sensitive attributes
* Set log level
* Enable logging to syslog

!!! Expand the Configuration

Expand your LDAP configuration to support SSH public key attributes

Normally SSH public keys are stored in the file {{File{~/.ssh/authorized_keys}}}.  Central storage in LDAP is an efficient way to make these SSH keys available for use on all systems while demonstrating how LDAP can be further customized and extended.

You will need to perform these tasks to enable support for SSH public keys:

* A schema needs to be included which describes the SSH public key attributes for our LDAP entries.  Add the appropriate schema to the slapd.conf file:
** Install the package openssh-ldap.  This package will provide the LDAP schema and SSH script used for checking an LDAP directory for SSH public keys
** Copy {{File{/usr/share/doc/openssh-ldap-5.3p1/openssh-lpk-openldap.schema}}} to {{File{/opt/work/openldap/etc/openldap/schema/}}}
** Add this line to {{File{slapd.conf}}} with the other include statements
include         /opt/work/openldap/etc/openldap/schema/openssh-lpk-openldap.schema
** Restart slapd

* Expand the LDAP entry for your user to support the new sshPublicKey attribute
** Install the package ldapvi.  This tool is the easiest way to make small modifications to LDAP database entries.  The ldapvi package can only be found in the epel repository.
** Use ldapvi to edit your LDAP user entries.  ldapvi will display your LDAP information in the vi editor, saving any changes back to the LDAP database when you quit vi.
{{Command{ldapvi -h localhost -D cn=root,dc=//username//,dc=cs407,dc=net &#045;-discover}}}
** Add this object class attribute for each of your users.  This allows the addition of attributes from the ldapPublicKey schema
objectClass: ldapPublicKey
** Add this attribute to my user account information.
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjDXBhIjaHcNNsNXkWxHmuwnU1+q0mMXSdobP+DP/X/57j9Txne6akT1nN8uF5YrTpRN/pIlKhsPFHVHjdPRzllV4vSBNyU8HWQmhPYjAvMsKGURU7PcQG40gkSe8hWCMRjGt37yj25c9mvb1A9hsC42jGIK5VlzoJPN/e8JRm7vXA7GFfrrutsYItnU3T1AG+B4tv/OyUE+xHkDcrdGPjn8M76mxgkBH1f/CyhOAC0D+ldQ5KXpgBm7P8oKhVDAXXJhoWMmpMjWiYRGVHEIJrnptBK9SznSvwN82K3H3jITuGlbtZOek9MBXPY5hRPb7PC6j6w5npF0Q/ZiEOmnIb merantn@cs407-2
** Generate a SSH keypair if you do not already have one.  Run {{Command{ssh-keygen}}} to do so.
** Add a sshPublicKey attribute to your LDAP record similar to the above, associating your public SSH key with your LDAP entry.
** Save and quit from ldapvi ( :wq )
** Answer ''y'' when prompted for an action to take.  This will save your changes back to the LDAP database

* Configure SSH to use SSH public keys stored in LDAP
** Edit {{File{/etc/ssh/sshd_config}}}
** Activate (uncomment) these two configuration statements:
~AuthorizedKeysCommand none 
~AuthorizedKeysCommandRunAs nobody
** For ~AuthorizedKeysCommand, change none to /usr/libexec/openssh/ssh-ldap-wrapper
** Restart sshd

* Download the LDAP client configuration file to your system:
* Be sure to change this config file after downloading to match your environment (change my username to yours)
wget -O /etc/openldap/ldap.conf
* Create the symbolic link {{File{/etc/ssh/ldap.conf}}} pointing to the file {{File{/etc/openldap/ldap.conf}}}
*  Test SSH public key retrieval from LDAP by executing {{Command{/usr/libexec/openssh/ssh-ldap-helper -d -s merantn -v}}}.  You may receive the following error instead of an SSH public key.
debug1: Reading configuration data /etc/ssh/ldap.conf
debug1: LDAP do connect
ldap_starttls_s: Connect error

If you do, stop here, examine your /etc/openldap/ldap.conf file and your SSL certificates and think about why we may be unable to connect with SSL.  Be prepared to discuss the problem next class.

We will work with this further next week, testing it with a user account once the client configuration is in place.
!! [[Lab 28 - OpenLDAP Clients]]
Assigned [[Mar 25|Day 16]], Due Mar 30

Ensure your www and files ~VMs are configured to authenticate against your ~OpenLDAP server on auth.  Apply the configuration from [[Day 16]].

Configure SSH on www and files to support obtaining SSH keys from LDAP:
* Install the package openssh-ldap. 
* Edit /etc/ssh/sshd_config
** Activate (uncomment) these two configuration statements:
~AuthorizedKeysCommand none 
~AuthorizedKeysCommandRunAs nobody
** For ~AuthorizedKeysCommand, change none to /usr/libexec/openssh/ssh-ldap-wrapper
** Restart sshd
* Create the symbolic link /etc/ssh/ldap.conf pointing to the file /etc/openldap/ldap.conf
* Test SSH public key retrieval from LDAP by executing /usr/libexec/openssh/ssh-ldap-wrapper merantn.

You should now be able to connect to your ~VMs as your user.  Be sure to add your account and merantn to the wheel group.

Generate an LDIF file containing your complete LDAP user entry
* {{Command{ldapsearch -LLL -h directory -D cn=root,dc=''username'',dc=cs407,dc=net -b ou=people,dc=''username'',dc=cs407,dc=net -W '(uid=''username'')' }}}
* Paste this output into ~/cs407/labs/cs407-lab28-//username//.ldif
!! [[Lab 29 - Backups & Cron]]
Assigned [[Mar 30|Day 17]], Due Apr 1

!!! Backup script:

Write a bash shell script which will use the dump utility to back up your auth VM's /opt/work filesystem to the files VM
Save your script on auth as /root/scripts/
Copy it to your home directory as ~/cs407/labs/cs407-lab29-//username//.sh

Your script must:
* Mount the /opt/backups/ filesystem from your file server if it is not already mounted.  ({{Command{man mountpoint}}}.  Evaluate exit status:  {{Command{mountpoint -q /opt/backups || mount /opt/backups}}}
* Create the directory /opt/backups&#047;//hostname//&#047; if it does not already exist.
* Use the dump utility to back up the filesystem and save the dump file to the directory /opt/backups&#047;//hostname//&#047; with an appropriate file name, such as work.$date.$level.dump.bz2
** where $date is a 6 digit YYMMDD date  (see date manpage)
** and $level is the dump level
* The dump file is to be bzip2 compressed
* Accept the dump level as an optional command line argument to your script
* If no argument is specified, use a dump level on the following schedule:
** Level 0 on the first day of the month
** Level 1 on Sunday
** Level 2 on each remaining day of the week
* Generate an appropriate syslog message noting success or failure of the backups
** Direct this message to the user facility and info severity level
** Tag = Backups
** {{Command{man logger}}}

Also check the date command man page for date formatting codes

This should get you started:
# File name:
# Author:
# Date Written:
# Assignment:
# Purpose:
# Description:

# Test for a command line argument and ensure it is a single digit
if [ $(expr "$1" : '^[0-9]\{1,\}$') -eq 1 ]

# Else, see if it is currently the first day of the month
elif [ $(date +%d) = "01" ]

# If a valid level cannot be determined from our argument or if statement above
# display usage and error out with positive exit status
        echo Error: Invalid level
        echo Usage: $0 [0-9]
	# Execute logger here to record this 
        exit 1

echo Level: $level

!!! Cron:

Create the following cron task on auth:

* Execute the backup script daily at 4am

!! [[Lab 30 - DNSSEC Signing]]
Assigned [[Mar 30|Day 17]], Due Apr 6

Examining your DNSSEC RRSIG records will show an expiration date attached to each:

{{Command{dig any}}}

The zone must be resigned periodically in order to prevent our RRSIG records from expiring.  

!!! 1. Write a DNSSEC signing shell script

Create a shell script which will increment your zone serial number and resign the zone.  

Save your script on auth as /etc/named/master/
Copy it to your home directory as ~/cs407/labs/

Your script shall extract the current SOA serial number from the unsigned zone file.  Isolate the date and sequence number from the serial, saving each to a variable.
- If the date is today, increment the sequence number in the new serial.
- If the date is not today, set the date portion of the new serial number to today's date and reset the sequence number to 00.

Run the appropriate dnssec-signzone command string to resign your zone

Run the appropriate command to reload your forward zone (and only your forward zone).

!!! 2. Schedule via cron

* Execute your DNSSEC signing script every two weeks at midnight, mailing the output to your CS account
** Output can be mailed by piping it to the mail command
** ie:  | mail -s "your subject"  //username//
** The mail command will need to be installed from package.
!! [[Lab 31 - Network enumeration]]
Assigned [[Apr 1|Day 18]], Due Apr 6

Map out required network connections for your web VM.  We will use this information as the basis of Monday's firewall lecture.

The netstat & lsof commands may prove useful. 
Don't neglect outbound traffic

Create a document (text, spreadsheet, etc) of your choosing.  Complete the table below to contain the following information for all required network connections to and from your VM.

Save the file to ~/cs407/labs/cs407-lab31-//username//.//ext//  where //ext// is an appropriate extension for your file type.

| !Port | !Proto | !Direction | !Scope | !Description |
| 22 | TCP | In | |SSH connections from my class network|
| 22 | TCP | In | |SSH connections from the CS server net|
| 22 | TCP | In | |SSH connections from the C012 Linux Lab|
| 22 | TCP | In | |SSH checks from the nagios server|
| 123 | UDP | In | | |
!! [[Lab 32 - Host-based Firewalls]]
Assigned [[Apr 6|Day 18]], Due Apr 13

Fully configure and enable the firewall on the web, auth and files ~VMs.

!!! Inbound:
- Globally allow all appropriate services (www & DNS)
- Restrict access to internal services (ie: NFS, LDAP) to the local network only (your /29)
- Create a SSH chain to allow SSH from your network, the CS servers, nagios, and the C012 linux lab.
- Be sure to allow to fully communicate with the systems.
- Add additional rules as you see fit.
- Default to deny inbound traffic.

!!! Outbound (web VM only):
- Provide egress filtering for the web VM
- Allow established connections
- Allow for communication with our yum repos
- Allow outbound connections for required services
- Default to deny outbound traffic

Save your firewall rulesets to ~/cs407/labs/cs407-lab32-//username//-//hostname//.txt
 - where //hostname// is one of {www,auth,files}
!! [[Lab 33 - System enumeration and infiltration]]
Assigned [[Apr 8|Day 20]], Due Apr 15

!!! Enumerate the system at and gain access.  

Discover all you can about this host and compromise the system.  You are not limited to external views.

Compile a report of your findings.  Be sure to include:
* What you found
* How you found it
* Recommendations for a fix or improvement

Attempt to reach these checkpoints:
* display the contents of the passwd file
* identify the process consuming the CPU.  Provide as much detail on it as possible.
* Display and report the highest flag you are able to access:
## /tmp/t-flag.txt
## /home/paco/p-flag.txt
## /root/r-flag.txt

There are two ways to obtain root.  One subtle and one easier to obtain.

Be sure to detail how you obtained the above information.  Save your report to ~/cs407/labs/cs407-lab33-//username//.txt

''If you save any files to the system, please delete them when you are done.''
!! [[Lab 34 - Bring mail server online]]
Assigned [[Day 22]], Due Apr 22

Bring your next virtual machine online.  We will work with this system on Wednesday to begin configuring it for use as a email server.

Accomplish the following tasks as well as any other generic steps from your lab notebook which may be necessary to add a new system to our class network.

Configure networking:
* Set hostname to mail.//username//
* Use the 5th IP address in your range
Create appropriate DNS records
Update the OS
Create a volume group named ''Storage'' to contain:
* a 256mb mirrored volume named work
* a 256mb mirrored volume named mail
Mount both logical volumes
* Mount the work LV to /opt/work
* Mount the mail LV to /var/mail
Add both logical volumes to fstab for mount on system startup
Provide LDAP authentication from your auth server

April 22nd checkpoint
Complete the remainder prior to April 27th:

Provide NFS home directory storage from your file server
 - mount /home from files to mail
Harden remote logins:
* Add the local admin account.  Ensure it is accessible via the previously provided SSH public key.
* Disable direct login as root
* Require wheel group membership to use su
* Add the admin user to the wheel group
Regenerate SSH host keys
Create SSHFP DNS records
!! [[Lab 35 - Install Exim]]
Assigned [[Apr 22|Day 23]], Due Apr 27

Ensure your mail server is properly installed. We will configure and bring it online next week.  

!!! Finish configuration from [[Lab 34|Lab 34 - Bring mail server online]]

!!! Set up a tmpfs for compile space

mkdir -p /opt/src
mount -t tmpfs -o size=32m tmpfs /opt/src

!!! Create local service account and group for exim. 

Use uid & gid of 52

!!! Install Exim from source
*Install dependencies:  perl pcre-devel db4-devel openldap-devel openssl-devel
*Download the latest version of [[Exim|]] source code to /opt/src/
* unpack
* Check out README file 
* Configure makefile
** cp src/EDITME to Local/Makefile
** Scan the Makefile and apply the following edits:
**''NOTE:''  Replace $ver with the full exim version number 
** Set ~BIN_DIRECTORY to /opt/work/exim_$ver/bin
**~CONFIGURE_FILE to /opt/work/exim_$ver/etc/exim.conf
**~EXIM_USER to exim
**Enable the following:
**Add this line after your LDAP settings:
***~LOOKUP_LIBS=-L/usr/local/lib -lldap -llber
**Disable (comment out) ~EXIM_MONITOR
***~TLS_LIBS=-L/usr/local/openssl/lib -lssl -lcrypto
***Set ~LOG_FILE_PATH to /var/log/exim/exim_%s.log
***~SYSTEM_ALIASES_FILE to /opt/work/exim_$ver/etc/aliases
* compile exim
* install exim
* create symlink in /opt/work to the installed exim directory
* Create the directory /var/log/exim/ and change ownership to exim:exim

!!! Download SSL CA certificate and add it to the cert bundle:

wget -O /etc/pki/tls/certs/cs407CA.crt
openssl x509 -text -noout -in /etc/pki/tls/certs/cs407CA.crt >> /etc/pki/tls/certs/ca-bundle.crt
cat /etc/pki/tls/certs/cs407CA.crt >> /etc/pki/tls/certs/ca-bundle.crt
!! [[Lab 36 - Configure exim and bring online]]
Assigned [[Apr 27|Day 24]].  Due Apr 29

Bring Exim online and allow for mail delivery to network users

!!! Configure Null client
configure postfix to relay mail through your mail server
Edit the /etc/postfix/
Search for relayhost

!!! Optional:  Add Rewrite rule
Mail sent from the command line on your web server will appear as coming from //username//@www.//username//  Investigate the Exim rewrite rules to explore the possibility of removing the host name from the email address (in this case, the www).
!! [[Lab 37 - Add Anti-Spam support]]
Assigned [[Apr 27|Day 24]].  Optional - will not be graded.

!!! Implement one anti-spam component, such as:
 - Antivirus (~ClamAV)
 - spamassassin
 - grey listing
 - ~RBLs
// //''Name:'' Calendar plugin
// //''Version:'' 0.1.0
// //''Author:'' SteveRumsby

// //''Syntax:''
// //<< {{{listTags tag //sort// //prefix//}}} >>

// //''Description:''
// //Generate a list of tiddlers tagged with the given tag.
// //If both //sort// and //prefix// are omitted the list is sorted in increasing order of title, with one tiddler per line.
// //If //sort// is specified the list is sorted in increasing order of the given tiddler property. Possible properties are: title. modified, modifier.
// //If //prefix// is specified the given string is inserted before the tiddler title. The insertion happens before the text is wikified. This can be used to generated bulleted or numbered lists.

// //''Examples:''
// //<< {{{listTags usage}}} >> - generate a plain list of all tiddlers tagged with tag //usage//, sorted by title
// //<< {{{listTags usage modified}}} >> - the same list, with most recently modified tiddlers last
// //<< {{{listTags usage title #}}} >> - generate a numbered list if tiddlers tagged with //usage//, sorted by title

// //''Code section:''
version.extensions.listTags = {major: 0, minor: 1, revision: 0, date: new Date(2005, 6,16)};

config.macros.listTags = {
text: "Hello"

config.macros.listTags.handler = function(place,macroName,params)
 var tagged = store.getTaggedTiddlers(params[0], params[1]);
 var string = "";
 for(var r=0;r<tagged.length;r++)
 if(params[2]) string = string + params[2] + " ";
 string = string + "[[" + tagged[r].title + "]]\n";
 wikify(string, place, null, null);
&nbsp; <<defaultHome>>  [[Notebook]]  [[Virtual Machines]]  [[Outline]]  [[Projects]]  [[Grades]]  [[Calendar]]

''NestedSlidersPlugin for TiddlyWiki version 1.2.x and 2.0''
^^author: Eric Shulman
license: [[Creative Commons Attribution-ShareAlike 2.5 License|]]^^

Quickly make any tiddler content into an expandable 'slider' panel, without needing to create a separate tiddler to contain the slider content.  Optional syntax allows ''default to open'', ''custom button label/tooltip'' and ''automatic blockquote formatting.''

You can also 'nest' these sliders as deep as you like (see complex nesting example below), so that expandable 'tree-like' hierarchical displays can be created.  This is most useful when converting existing in-line text content to create in-line annotations, footnotes, context-sensitive help, or other subordinate information displays.

For more details, please click on a section headline below:
Debugging messages for 'lazy sliders' deferred rendering:
<<option chkDebugLazySliderDefer>> show debugging alert when deferring slider rendering
<<option chkDebugLazySliderRender>> show debugging alert when deferred slider is actually rendered
When installed, this plugin adds new wiki syntax for embedding 'slider' panels directly into tiddler content.  Use {{{+++}}} and {{{===}}} to delimit the slider content.  Additional optional syntax elements let you specify
*default to open
*heading level
*floater (with optional CSS width value)
*mouse auto rollover
*custom label/tooltip/accesskey
*automatic blockquote
*deferred rendering
The complete syntax, using all options, is:
content goes here
* {{{+++}}} (or {{{++++}}}) and {{{===}}}^^
marks the start and end of the slider definition, respectively.  When the extra {{{+}}} is used, the slider will be open when initially displayed.^^
* {{{(cookiename)}}}^^
saves the slider opened/closed state, and restores this state whenever the slider is re-rendered.^^
* {{{!}}} through {{{!!!!!}}}^^
displays the slider label using a formatted headline (Hn) style instead of a button/link style^^
* {{{^width^}}} (or just {{{^}}})^^
makes the slider 'float' on top of other content rather than shifting that content downward.  'width' must be a valid CSS value (e.g., "30em", "180px", "50%", etc.).  If omitted, the default width is "auto" (i.e., fit to content)^^
* {{{*}}}^^
automatically opens/closes slider on "rollover" as well as when clicked^^
* {{{[label=key|tooltip]}}}^^
uses custom label/tooltip/accesskey.  {{{=key}}} and {{{|tooltip}}} are optional.  'key' is must be a ''single letter only''.  Default labels/tootips are: ">" (more) and "<" (less), with no default access key assignment.^^
* {{{">"}}} //(without the quotes)//^^
automatically adds blockquote formatting to slider content^^
* {{{"..."}}} //(without the quotes)//^^
defers rendering of closed sliders until the first time they are opened.  //Note: deferred rendering may produce unexpected results in some cases.  Use with care.//^^

//Note: to make slider definitions easier to read and recognize when editing a tiddler, newlines immediately following the {{{+++}}} 'start slider' or preceding the {{{===}}} 'end slider' sequence are automatically supressed so that excess whitespace is eliminated from the output.//
simple in-line slider: 
use a custom label and tooltip: 
content automatically blockquoted: 
all options combined //(default open, cookie, heading, sized floater, rollover, label/tooltip/key, blockquoted, deferred)//
++++(testcookie)!!!^30em^*[label=Z|click or press Alt-Z to open]>...
++++(testcookie)!!!^30em^*[label=Z|click or press Alt-Z to open]>...
complex nesting example:
+++^[get info...=I|click for information or press Alt-I]
   put some general information here, plus a floating slider with more specific info:
   +++^10em^[view details...|click for details]
      put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===
+++^[get info...=I|click for information or press Alt-I]
   put some general information here, plus a floating slider with more specific info:
   +++^10em^[view details...|click for details]
      put some detail here, which could include a rollover with a +++^25em^*[glossary definition]explaining technical terms===
nested floaters
>menu: <<tiddler NestedSlidersExample>>
(see [[NestedSlidersExample]] for definition)
import (or copy/paste) the following tiddlers into your document:
''NestedSlidersPlugin'' (tagged with <<tag systemConfig>>)
!!!!!Revision History
''2006.05.11 - 1.9.0'' added optional '^width^' syntax for floating sliders and '=key' syntax for setting an access key on a slider label
''2006.05.09 - 1.8.0'' in onClickNestedSlider(), when showing panel, set focus to first child input/textarea/select element
''2006.04.24 - 1.7.8'' in adjustSliderPos(), if floating panel is contained inside another floating panel, subtract offset of containing panel to find correct position
''2006.02.16 - 1.7.7'' corrected deferred rendering to account for use-case where show/hide state is tracked in a cookie
''2006.02.15 - 1.7.6'' in adjustSliderPos(), ensure that floating panel is positioned completely within the browser window (i.e., does not go beyond the right edge of the browser window)
''2006.02.04 - 1.7.5'' add 'var' to unintended global variable declarations to avoid FireFox crash bug when assigning to globals
''2006.01.18 - 1.7.4'' only define adjustSliderPos() function if it has not already been provided by another plugin.  This lets other plugins 'hijack' the function even when they are loaded first.
''2006.01.16 - 1.7.3'' added adjustSliderPos(place,btn,panel,panelClass) function to permit specialized logic for placement of floating panels.  While it provides improved placement for many uses of floating panels, it exhibits a relative offset positioning error when used within *nested* floating panels.  Short-term workaround is to only adjust the position for 'top-level' floaters.
''2006.01.16 - 1.7.2'' added button property to slider panel elements so that slider panel can tell which button it belongs to.  Also, re-activated and corrected animation handling so that nested sliders aren't clipped by hijacking Slider.prototype.stop so that "overflow:hidden" can be reset to "overflow:visible" after animation ends
''2006.01.14 - 1.7.1'' added optional "^" syntax for floating panels.  Defines new CSS class, ".floatingPanel", as an alternative for standard in-line ".sliderPanel" styles.
''2006.01.14 - 1.7.0'' added optional "*" syntax for rollover handling to show/hide slider without requiring a click (Based on a suggestion by tw4efl)
''2006.01.03 - 1.6.2'' When using optional "!" heading style, instead of creating a clickable "Hn" element, create an "A" element inside the "Hn" element.  (allows click-through in SlideShowPlugin, which captures nearly all click events, except for hyperlinks)
''2005.12.15 - 1.6.1'' added optional "..." syntax to invoke deferred ('lazy') rendering for initially hidden sliders
removed checkbox option for 'global' application of lazy sliders
''2005.11.25 - 1.6.0'' added optional handling for 'lazy sliders' (deferred rendering for initially hidden sliders)
''2005.11.21 - 1.5.1'' revised regular expressions: if present, a single newline //preceding// and/or //following// a slider definition will be suppressed so start/end syntax can be place on separate lines in the tiddler 'source' for improved readability.  Similarly, any whitespace (newlines, tabs, spaces, etc.) trailing the 'start slider' syntax or preceding the 'end slider' syntax is also suppressed.
''2005.11.20 - 1.5.0'' added (cookiename) syntax for optional tracking and restoring of slider open/close state
''2005.11.11 - 1.4.0'' added !!!!! syntax to render slider label as a header (Hn) style instead of a button/link style
''2005.11.07 - 1.3.0'' removed alternative syntax {{{(((}}} and {{{)))}}} (so they can be used by other
formatting extensions) and simplified/improved regular expressions to trim multiple excess newlines
''2005.11.05 - 1.2.1'' changed name to NestedSlidersPlugin
more documentation
''2005.11.04 - 1.2.0'' added alternative character-mode syntax {{{(((}}} and {{{)))}}}
tweaked "eat newlines" logic for line-mode {{{+++}}} and {{{===}}} syntax
''2005.11.03 - 1.1.1'' fixed toggling of default tooltips ("more..." and "less...") when a non-default button label is used
code cleanup, added documentation
''2005.11.03 - 1.1.0'' changed delimiter syntax from {{{(((}}} and {{{)))}}} to {{{+++}}} and {{{===}}}
changed name to EasySlidersPlugin
''2005.11.03 - 1.0.0'' initial public release
This feature was implemented by EricShulman from [[ELS Design Studios|http:/]] with initial research and suggestions from RodneyGomes, GeoffSlocock, and PaulPetterson.
version.extensions.nestedSliders = {major: 1, minor: 9, revision: 0, date: new Date(2006,5,11)};

// options for deferred rendering of sliders that are not initially displayed
if (config.options.chkDebugLazySliderDefer==undefined) config.options.chkDebugLazySliderDefer=false;
if (config.options.chkDebugLazySliderRender==undefined) config.options.chkDebugLazySliderRender=false;

// default styles for 'floating' class
setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
	background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");

config.formatters.push( {
	name: "nestedSliders",
	match: "\\n?\\+{3}",
	terminator: "\\s*\\={3}\\n?",
	lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\[\\>]*\\^)?)?(\\*)?(\\[[^\\]]*\\])?(\\>)?(\\.\\.\\.)?\\s*",
	handler: function(w)
			var lookaheadRegExp = new RegExp(this.lookahead,"mg");
			lookaheadRegExp.lastIndex = w.matchStart;
			var lookaheadMatch = lookaheadRegExp.exec(w.source)
			if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
				// location for rendering button and panel
				var place=w.output;

				// default to closed, no cookie, no accesskey
				var show="none"; var title=">"; var tooltip="show"; var cookie=""; var key="";

				// extra "+", default to open
				if (lookaheadMatch[1])
					{ show="block"; title="<"; tooltip="hide"; }

				// cookie, use saved open/closed state
				if (lookaheadMatch[2]) {
					if (config.options[cookie]==undefined)
						{ config.options[cookie] = (show=="block") }
					if (config.options[cookie])
						{ show="block"; title="<"; tooltip="hide"; }
						{ show="none"; title=">"; tooltip="show"; }

				// parse custom label/tooltip/accesskey: [label=X|tooltip]
				if (lookaheadMatch[6]) {
					title = lookaheadMatch[6].trim().slice(1,-1);
					var pos=title.indexOf("|");
					if (pos!=-1) { tooltip = title.substr(pos+1,title.length); title=title.substr(0,pos); }
					if (title.substr(title.length-2,1)=="=") { key=title.substr(title.length-1,1); title=title.slice(0,-2); }
					if (pos==-1) tooltip += " "+title; // default tooltip: "show/hide <title>"

				// create the button
				if (lookaheadMatch[3]) { // use "Hn" header format instead of button/link
					var lvl=(lookaheadMatch[3].length>6)?6:lookaheadMatch[3].length;
					var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,null,title);
					var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider);
				btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
				btn.keyparam=key; // save the access key letter ("" if none)
				if (key.length) {
					btn.setAttribute("accessKey",key); // init access key
					btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus

				// "non-click" MouseOver open/close slider
				if (lookaheadMatch[5]) btn.onmouseover=onClickNestedSlider;

				// create slider panel
				var panelClass=lookaheadMatch[4]?"floatingPanel":"sliderPanel";
				var panel=createTiddlyElement(place,"div",null,panelClass,null); = show;
				if (lookaheadMatch[4] && lookaheadMatch[4].length>2)[4].slice(1,-1); // custom width
				panel.button = btn; // so the slider panel know which button it belongs to

				// render slider (or defer until shown) 
				w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
				if ((show=="block")||!lookaheadMatch[8]) {
					// render now if panel is supposed to be shown or NOT deferred rendering
					// align slider/floater position with button
				else {
					var src = w.source.substr(w.nextMatch);
					var endpos=findMatchingDelimiter(src,"+++","===");
					w.nextMatch += endpos+3;
					if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
					if (config.options.chkDebugLazySliderDefer) alert("deferred '"+title+"':\n\n"+panel.getAttribute("raw"));

// TBD: ignore 'quoted' delimiters (e.g., "{{{+++foo===}}}" isn't really a slider)
function findMatchingDelimiter(src,starttext,endtext) {
	var startpos = 0;
	var endpos = src.indexOf(endtext);
	// check for nested delimiters
	while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
		// count number of nested 'starts'
		var startcount=0;
		var temp = src.substring(startpos,endpos-1);
		var pos=temp.indexOf(starttext);
		while (pos!=-1)  { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
		// set up to check for additional 'starts' after adjusting endpos
		// find endpos for corresponding number of matching 'ends'
		while (startcount && endpos!=-1) {
			endpos = src.indexOf(endtext,endpos+endtext.length);
	return (endpos==-1)?src.length:endpos;

	if (!e) var e = window.event;
	var theTarget = resolveTarget(e);
	var theLabel =;
	var theSlider = theTarget.sliderPanel
	var isOpen =!="none";
	// if using default button labels, toggle labels
	if (theLabel==">") = "<";
	else if (theLabel=="<") = ">";
	// if using default tooltips, toggle tooltips
	if (theTarget.getAttribute("title")=="show")
	else if (theTarget.getAttribute("title")=="hide")
	if (theTarget.getAttribute("title")=="show "+theLabel)
		theTarget.setAttribute("title","hide "+theLabel);
	else if (theTarget.getAttribute("title")=="hide "+theLabel)
		theTarget.setAttribute("title","show "+theLabel);
	// deferred rendering (if needed)
	if (theSlider.getAttribute("rendered")=="false") {
		if (config.options.chkDebugLazySliderRender)
			alert("rendering '"+theLabel+"':\n\n"+theSlider.getAttribute("raw"));
		var place=theSlider;
		if (theSlider.getAttribute("blockquote")=="true")
	// show/hide the slider
		anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
	else = isOpen ? "none" : "block";
	// if showing panel, set focus to first 'focus-able' element in panel
	if (!="none") {
		var ctrls=theSlider.getElementsByTagName("*");
		for (var c=0; c<ctrls.length; c++) {
			var t=ctrls[c].tagName.toLowerCase();
			if (t=="input" || t=="textarea" || t=="select")
				{ ctrls[c].focus(); break; }
	if (this.sliderCookie && this.sliderCookie.length)
		{ config.options[this.sliderCookie]=!isOpen; saveOptionCookie(this.sliderCookie); }
	// align slider/floater position with target button
	return false;

// hijack animation handler 'stop' handler so overflow is visible after animation has completed
Slider.prototype.coreStop = Slider.prototype.stop;
Slider.prototype.stop = function() { this.coreStop(); = "visible"; }

// adjust panel position based on button position
if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel,panelClass) {
	if (panelClass=="floatingPanel") {
		var left=0;
		var top=btn.offsetHeight; 
		if (!="relative") {
			var left=findPosX(btn);
			var top=findPosY(btn)+btn.offsetHeight;
			var p=place; while (p && p.className!='floatingPanel') p=p.parentNode;
			if (p) { left-=findPosX(p); top-=findPosY(p); }
		if (left+panel.offsetWidth > getWindowWidth()) left=getWindowWidth()-panel.offsetWidth-10;"px";"px";

function getWindowWidth() {
		return document.width; // moz (FF)
	if(document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) )
		return document.documentElement.clientWidth; // IE6
	if(document.body && ( document.body.clientWidth || document.body.clientHeight ) )
		return document.body.clientWidth; // IE4
		return window.innerWidth; // IE - general
	return 0; // unknown
[[Material Sections]]

!!~CS307 Handouts
[[Command line summary handout|handouts/UnixCommandSummary.pdf]]
[[Substitution Handout|handouts/SubstitutionHandout.pdf]] (from tcsh man page)
[[ASCII Chart|handouts/ascii-chart.gif]]
[[Metacharacter Handout|handouts/Metacharacters.pdf]] - Metacharacters and how they differ in the shell & regular expression contexts.
[[Regular expression metacharacters]]
[[vi diagram handout|handouts/viDiagram.pdf]]
[[awk handout|handouts/awkHandout.pdf]]

!!~DogNET Information
[[C012 Lab diagram|]]

!!Reference Material
[[UNIX in a Nutshell|]] - Google books
[[The Linux Command Line (No Starch Press)|]]
[[UNIX Toolbox|]]
[[CS307 course notes|]]
[[Shell scripting notes]]
[[Table of Commands]]
|Created by|SaqImtiaz|
Open new tiddlers at the top of the screen.

Story.prototype.coreLewcidDisplayTiddler=Story.prototype.displayTiddler ;
Story.prototype.displayTiddler =
       var srcElement=null;
       if (document.getElementById(this.idPrefix + title))
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations
Also see AdvancedOptions

[[Day 22]] - Hack box review / Email server setup

* [[Lab 17]] - Expanded DNS: SSH & DANE (@@midterm@@)

* Read ~SysAdmin Section 19.3 (Pg 728) - LDAP
M [[Sep 29|Day 10]] - Time out - Shell shock, web exploits, and getting caught up
* [[Lab 11]] - Patch for shellshock
* [[Lab 04]] - Write shell script for returning graded labs
[[Apr 27|Day 24]] - Email
* [[Lab 36 - Configure exim and bring online]]
* [[Lab 37 - Add Anti-Spam support]]
[[Apr 22|Day 23]] - Drivers and the Kernel
* Read ~SysAdmin Chapter 20 - Email.  Stop at section 20.8 on page 775.
* [[Lab 35 - Install Exim]]
[[Apr 20|Day 22]] - Performance Monitoring
* [[Lab 34 - Bring mail server online]]
* Experiment with performance monitoring tools
* Work on accessing hack box
[[Apr 15|Day 21]] - Additional filesystem topics
* Read ~SysAdmin Chapter 13 - Drivers and the Kernel
[[Apr 8|Day 20]] - Patching and staying up to date
* [[Lab 33 - System enumeration and infiltration]]
* Read ~SysAdmin sections 22.7 (Pg 913) Chroot & 22.9 (Pg 922) MAC
[[Apr 6|Day 19]] - Host-based Firewalls
* [[Lab 32 - Host-based Firewalls]]
* Read ~SysAdmin sections 22.7 (Pg 913) Chroot & 22.9 (Pg 922) MAC
[[Apr 1|Day 18]] - Network / system enumeration and security tools 
* [[Lab 31 - Network enumeration]]
* Read ~SysAdmin sections 22.11 & 22.12 (Firewalls)
[[Mar 30|Day 17]] - Scheduled Tasks and Backups
* [[Lab 29 - Backups & Cron]] - auth: Create a backup and DNS scripts and schedule them to run via cron
* [[Lab 30 - DNSSEC Signing]] - auth: Create a script which will resign your DNSSEC records
* Reading:
** ~SysAdmin Chapter 21, stop at section 21.8
** ~SysAdmin Chapter 22, section 22.8
** Experiment with the netstat and nmap tools to discover open ports on local and remote systems
W [[Mar 25|Day 16]] - ~OpenLDAP & centralized authentication - clients
* [[Lab 28 - OpenLDAP Clients]]
* Read:
** ~SysAdmin Chapter 9 - Periodic Processes
** ~SysAdmin Chapter 10 - Backups (Stop at 10.7 on page 317)
M [[Mar 23|Day 15]] - ~OpenLDAP & centralized authentication
* [[Lab 27 - OpenLDAP Server]]
W [[Mar 17|Day 14]] - Crypto & securing communication
* [[Lab 25 - SSL Certificates]]
* [[Lab 26 - Install OpenLDAP]]
* Read ~SysAdmin Section 19.3 (Pg 728) - LDAP
* Project progress reports
M [[Mar 15|Day 13]] - NFS, file sharing and different file system types
* [[Lab 21 - NFS]] - Set up NFS server and mount /home on www & auth
* [[Lab 22 - Monitoring disk usage with Nagios]] - www, auth, files
* [[Lab 23 - Filesystem Options]]
* [[Lab 24 - hack1 break-in]]
* Read ~SysAdmin section 23.4 (pg 971) on SSL
W [[Mar 3|Day 12]] - Storage, standard filesystems, and LVM
* [[Lab 18 - Fix SSHFP Records]] - www, auth, files
* [[Lab 19 - Logical Volume Manager]] - files, www, auth: set up LVM ([[worksheet|labs/lab19.pdf]])
* [[Lab 20 - Move apache logs]]
* Read ~SysAdmin Chapter 8 - Sections 8.7 (246) to 8.10 (264) 
M [[Mar 2|Day 11]] - Access control and user management
* [[Lab 15 - VM Lockdown - Secure your VMs]] - Set up local user accounts & secure SSH
* [[Lab 16 - sudo]] - www: Grant admin access to apache configs and service restart
* [[Lab 17 - Bring the storage server online]]
* Read ~SysAdmin Chapter 8 - Storage up to section 8.8 on page 246
W [[Feb 24|Day 10]] - DNS Part 2
* [[Lab 14 - Additional DNS records]] - auth:  Create apex and SSHFP records
* Read ~SysAdmin Chapters 4 and 7
M [[Feb 23|Day 9]] - DNS Part 1
* [[Lab 12 - Bind config and zones]] - auth: Complete bind config, DNS zones, and bring bind online
* [[Lab 13 - DNS Security Extensions]] - auth: DNSSEC writeup and secure DNS zones
* Continue reading ~SysAdmin Chapter 17 - DNS
[[Feb 18|Day 8]] - Time & Logging
* [[Lab 10 - Time & Logging]] - www & auth: ntp, syslog & central logging
* [[Lab 11 - DNS part 1]] - Complete [[Lab 11 worksheet|labs/lab11.pdf]]
W [[Feb 16|Day 7]] - Proxies, tunnels, and Web services
* [[Lab 08 - Set up MediaWiki]]
* [[Lab 09 - Bring auth VM online]]
* Read ~SysAdmin Chapter 11 - syslog and log files
W [[Feb 11|Day 6]] - UNIX command line and manipulating the shell environment
* [[Lab 06 - Customize your environment]]
* [[Lab 07 - Lab return shell script]]
* Read ~SysAdmin Chapter 23 - Web Hosting
M [[Feb 9|Day 5]] - Documentation, Expanding our systems: Working with rpm & yum, installing software from package and source
* [[Lab 04 - VM updates & software installation]]
* [[Lab 05 - Web Server]] - Install and bring online mySQL and apache with php
* Read ~SysAdmin section 2.1 - Shell basics
* Start keeping good VM notes 
W [[Feb 04|Day 4]] - Unix review, lab 1 review, working with SSH & screen
M Feb 2 - Snow day
W [[Jan 28|Day 3]] - Starting and Stopping, init & run levels, layout of the operating system, system configuration (/etc/ files).
* Read ~SysAdmin Chapter 12 - Software Installation and Management
* [[Lab 03 - Install man]] - Install the man utility on your test and www ~VMs
M [[Jan 26|Day 2]] - Basic networking & Unix refresher part 2
* [[Lab 02 - Bring VMs Online]] - Ensure your test and web server ~VMs are online
* Become familiar with your ~VMs
* Read ~SysAdmin Chapter 3 (skip over Solaris and AIX parts)
W [[Jan 21|Day 1]] - Unix refresher
* [[Lab 00 - Connect to fang]]
* [[Lab 01 - UNIX Refresher]] - ([[Worksheet|labs/Lab1.pdf]])
* Unix Review & Review ~SysAdmin Chapter 1

<<tiddler [[Lab 00 - Connect to fang]]>>
<<tiddler [[Lab 01 - UNIX Refresher]]>>
<<tiddler [[Lab 02 - Bring VMs Online]]>>
<<tiddler [[Lab 03 - Install man]]>>
<<tiddler [[Lab 04 - VM updates & software installation]]>>
<<tiddler [[Lab 05 - Web Server]]>>
<<tiddler [[Lab 06 - Customize your environment]]>>
<<tiddler [[Lab 07 - Lab return shell script]]>>
<<tiddler [[Lab 08 - Set up MediaWiki]]>>
<<tiddler [[Lab 09 - Bring auth VM online]]>>
<<tiddler [[Lab 10 - Time & Logging]]>>
<<tiddler [[Lab 11 - DNS part 1]]>>
<<tiddler [[Lab 12 - Bind config and zones]]>>
<<tiddler [[Lab 13 - DNS Security Extensions]]>>
<<tiddler [[Lab 14 - Additional DNS records]]>>
<<tiddler [[Lab 15 - VM Lockdown - Secure your VMs]]>>
<<tiddler [[Lab 16 - sudo]]>>
<<tiddler [[Lab 17 - Bring the storage server online]]>>
<<tiddler [[Lab 18 - Fix SSHFP Records]]>>
<<tiddler [[Lab 19 - Logical Volume Manager]]>>
<<tiddler [[Lab 20 - Move apache logs]]>>
<<tiddler [[Lab 21 - NFS]]>>
<<tiddler [[Lab 22 - Monitoring disk usage with Nagios]]>>
<<tiddler [[Lab 23 - Filesystem Options]]>>
<<tiddler [[Lab 24 - hack1 break-in]]>>
<<tiddler [[Lab 25 - SSL Certificates]]>>
<<tiddler [[Lab 26 - Install OpenLDAP]]>>
<<tiddler [[Lab 27 - OpenLDAP Server]]>>
<<tiddler [[Lab 28 - OpenLDAP Clients]]>>
<<tiddler [[Lab 29 - Backups & Cron]]>>
<<tiddler [[Lab 30 - DNSSEC Signing]]>>
<<tiddler [[Lab 31 - Network enumeration]]>>
<<tiddler [[Lab 32 - Host-based Firewalls]]>>
<<tiddler [[Lab 33 - System enumeration and infiltration]]>>
<<tiddler [[Lab 34 - Bring mail server online]]>>
<<tiddler [[Lab 35 - Install Exim]]>>
<<tiddler [[Lab 36 - Configure exim and bring online]]>>
<<tiddler [[Lab 37 - Add Anti-Spam support]]>>
<div class='header' macro='gradient vert #000 #069'>
<div id='topTitle' class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='topTitle' class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;&nbsp;&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<div id='rightMenu' refresh='content' tiddler='RightMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
function onClickDefaultHome(e) {
config.options.txtDefaultTiddlers = "";
var start = store.getTiddlerText("DefaultTiddlers");

config.macros["defaultHome"] = {label: "Home", prompt: "Show the default tiddlers", title: "Home"};
config.macros.defaultHome.handler = function(place) {

config.macros.listTags = { text: "Hello" };
config.macros.listTags.handler = function(place,macroName,params)
 var tagged = store.getTaggedTiddlers(params[0]);
 var ul = createTiddlyElement(place,"ul",null,null,"");
 for(var r=0;r<tagged.length;r++)
 var li = createTiddlyElement(ul,"li",null,null,"");
Type the text for 'Plugins'
!! Fall 2014
| !Username | !Topic | !Submissions |
| butterta |Web Security||
| dancksj |DNSSEC Lookaside Validation|[[Proposal|projects/1409/cs407-dancksj-proposal.pdf]] - [[Writeup|projects/1409/cs407-dancksj-Project.pdf]]|
| hartmajh |IT Automation|[[Proposal|projects/1409/cs407-hartmajh-proposal.pdf]] - [[Writeup|projects/1409/cs407-hartmajh-Project.pdf]]|
| parzycl1 |nmap in depth|[[Proposal|projects/1409/cs407-parzycl1-proposal.pdf]] - [[Writeup|projects/1409/cs407-parzycl1-Project.pdf]]|
| pasquaja |nginx|[[Proposal|projects/1409/cs407-pasquaja-proposal.pdf]] - [[Writeup|projects/1409/cs407-pasquaja-Project.pdf]]|
| vocea |IDS/Snort|[[Proposal|projects/1409/cs407-vocea-proposal.pdf]] - [[Writeup|projects/1409/cs407-vocea-Project.pdf]]|
| vrydagm |Honeypots|[[Proposal|projects/1409/cs407-vrydagm-proposal.pdf]] - [[Writeup|projects/1409/cs407-vrydagm-Project.pdf]]|

!! Spring 2014
| ! |>| !Project 1 |>| !Project 2 |
| !Username | !Topic | !Submissions | !Topic | !Submissions |
| chauras |iptables| [[Proposal|projects/p1/proposal/ncs522-chauras-iptables-proposal.pdf]] - [[Writeup|projects/p1/final/project1-ncs522-charuas.pdf]] |OSSEC *| [[Proposal|projects/p2/proposal/ncs522-chauras-projpro2.pdf]] - [[Writeup|projects/p2/final/ncs522-chauras-ossec.pdf]] |
| collisnj |Mozilla Sync| [[Proposal|projects/p1/proposal/ncs522-collisnj-mozillasync-proposal.pdf]] - [[Writeup|projects/p1/final/ncs522-collisnj-mozillasync.pdf]] |DNSSEC key rotation *| [[Proposal|projects/p2/proposal/ncs522-collisnj-dnsseckeyrotation-proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-collisnj-dnsseckeyrotation.pdf]] |
| lisim |Port monitoring| [[Proposal|projects/p1/proposal/ncs522-lisim-port_monitor-proposal.pdf]] - [[Writeup|projects/p1/final/Project_1_Writeup_lisim.pdf]]  |2factor Auth *| [[Proposal|projects/p2/proposal/ncs522-lisim-google_2fa_proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-lisim-google_2fa_writeup.pdf]] |
| martind5 |Puppet *| [[Proposal|projects/p1/proposal/ncs522-martind5-puppet.pdf]] - [[Writeup|projects/p1/final/ncs522-martind5-puppet.pdf]]  |Cucumber|  [[Proposal|projects/p2/proposal/ncs522-martind5-cucumber-proposal2.pdf]] - [[Writeup|projects/p2/final/ncs522-martind5-cucumber.pdf]] |
| maumb |ssh security *| [[Proposal|projects/p1/proposal/ncs522-maumb-sshd-proposal.pdf]] - [[Writeup|projects/p1/final/ncs522-maumb-ssh_sec.pdf]] |Two Factor|  [[Proposal|projects/p2/proposal/ncs522-maumb-2factorauth-proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-maumb-2factorauth.pdf]] |
| milleraj |IDS| [[Proposal|projects/p1/proposal/ncs522-milleraj-ids-proposal.pdf]] - [[Writeup|projects/p1/final/ncs522-milleraj-ids.pdf]]  |Mininet *|  [[Proposal|projects/p2/proposal/ncs522-milleraj-mininet-proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-milleraj-mininet.pdf]] |
| wellssj |virtual vs physical| [[Proposal|projects/p1/proposal/ncs522-wellssj-Virtualization-proposal.pdf]] - [[Writeup|projects/p1/final/ncs522-wellssj-Virtualized_Versus_Physical_Servers.pdf]]  |SSL *|  [[Proposal|projects/p2/proposal/ncs522-wellssj-SSL-proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-wellssj-SSL.pdf]] |
| widricd |DNS failover *|  [[Proposal|projects/p1/proposal/ncs522-widricd-dnsfailover-proposal.pdf]] - [[Writeup|projects/p1/final/servers_linux_dns_bind_dnssec_inline_signing-widricd.pdf]] |Network boot servers| [[Proposal|projects/p2/proposal/ncs522-widricd-pxeboot-proposal.pdf]] - [[Writeup|projects/p2/final/ncs522-widricd-pxeboot.pdf]] |
|>|>|>|>| * = Presenting  |

!! Fall 2013
| !Username | !Project 1 | !Project 2 |
| brennap |[[DNS split horizon|projects/brennap_cs407_writeup1.pdf]] *|[[SELinux|projects/brennap_cs407_writeup2.pdf]]|
| clarkz |[[Owncloud|projects/clarkz-owncloud.pdf]]|[[zfs|projects/clarkz-zfs.pdf]] *|
| donnelpc |[[Amazon EC2|projects/DonnellyCS407Project1]]|[[SpamAssassin|projects/spamassassin.pdf]] *|
| freemanj |[[mySQL Replication|projects/mysql repilcation how to.pdf]]|[[Grey Listing|projects/freemanj_Cs407_greylisting.txt]] *|
| halberl |[[Webmail|projects/roundcube.pdf]]|[[CUPS|projects/cups.pdf]]|
| lapinsm |[[Config RCS|projects/Lapinski_CS407_Subversion.pdf]]|[[sar|projects/Lapinski_CS407_Sar_Writeup.pdf]] *|
| pittarz |[[dig|projects/pittarz_project1.txt]] *|[[Exim auth|projects/pittarz_project2.pdf]]|
| schuchg |[[DNSSEC|projects/DNSSEC.pdf]] *|[[LDAP Replication|projects/LDAPrep.pdf]]|
| sleysr |[[LDAP Replication|projects/OpenLDAPrep.pdf]]|[[webmin|projects/WebMin.pdf]] *|
| vanderjr |[[fail2ban|]]|[[saltstack|projects/saltstack.pdf]] *|
|>|>| * = Presenting on Dec 11, 3pm |
! Semester Project

!! [[Previous semester projects]]

!! Current semester projects
| !Username | !Topic | !Submissions | ! |
| biscarm |Vuln Scanning| [[Proposal|projects/1501/cs407-biscarm-proposal.pdf]] - [[Writeup|projects/1501/cs407-biscarm-project.pdf]] ||
| brandtg |Linux Containers| [[Proposal|projects/1501/cs407-brandtg-proposal.pdf]] - [[Writeup|projects/1501/cs407-brandtg-project.pdf]] | * |
| dennism4 |Web High Availability| [[Proposal|projects/1501/cs407-dennism4-proposal.pdf]] - [[Writeup|projects/1501/cs407-dennism4-project.pdf]] | * |
| gomezd1 |Rasp Pi| [[Proposal|projects/1501/cs407-gomezd1-proposal.pdf]] - [[Writeup|projects/1501/cs407-gomezd1-project.pdf]] | * |
| hoganlt |Honeypots| [[Proposal|projects/1501/cs407-hoganlt-proposal.pdf]] - [[Writeup|projects/1501/cs407-hoganlt-Project.pdf]] ||
| hookz |Web log analysis| [[Proposal|projects/1501/cs407-hookz-proposal.pdf]] - [[Writeup|projects/1501/cs407-hookz-project.pdf]] ||
| hunga |Web Security| [[Proposal|projects/1501/cs407-hunga-proposal.pdf]] - [[Writeup|projects/1501/cs407-hunga-project.pdf]] | * |
| knappjf |Configuration Management| [[Writeup|projects/1501/cs407-knappjf-project.pdf]] | * |
| morgansm |~Anti-Spam| [[Proposal|projects/1501/cs407-morgansm-proposal.pdf]] - [[Writeup|projects/1501/cs407-morgansm-Project.pdf]] | * |
| reevess |Custom Kernel| [[Proposal|projects/1501/cs407-reevess-proposal.pdf]] - [[Writeup|projects/1501/cs407-reevess-Project.pdf]] | * |
| spierd |Docker| [[Proposal|projects/1501/cs407-spierd-proposal.pdf]] - [[Writeup|projects/1501/cs407-spierd-Project.pdf]] | * |
| zaydons |~TiddlyWeb| [[Proposal|projects/1501/cs407-zaydons-proposal.pdf]] - [[Writeup|projects/1501/cs407-zaydons-Project.pdf]] ||
|>|>|>| * = Presenting May 4 at 3pm |
/% | ! |>| !Project 1 | %/
/% [[Proposal|projects/1501/cs407-username-proposal.pdf]] - [[Writeup|projects/1501/cs407-username-project.pdf]] %/

!! Project Summary
* One small project to be completed over the course of the semester
** with a brief how-to or tutorial writeup and brief presentation
* Find something cool to check out, explore, and learn
* This is your opportunity to present new material to the class
* Either explore something we talked about in more detail
* Or find something I'm not planning to discuss
* The goal is to expand the reach of the course beyond material I'm able to cover 
** and for us to learn from you.

!! Timetable
* Topic selection:  2/20
* Proposal: 2/27
* Progress reports: 3/23 & 4/10
* Completion & final deliverable: 4/23
* Presentation: 5/4 at 3pm

!! Topic selection
* The topic for your project accompanied with a very brief description of what you plan to do and what the final outcome will be
* Sent to me via email
* Email subject must be:  ''~CS407/~NCS522 Project topic''
* I will review your project topic and reply to either proceed or we will discuss your topic further.

!! Project proposal  (5%)
* The full project proposal is a more formal description of your project
* Be sure to include additional detail on what you plan to do, such as:
** how you plan to do it
** any resources you will require
** anticipated timeline and milestones
** the expected final project outcome and deliverable
* Save a PDF named {{File{cs407-//username//-proposal.pdf}}} to your {{File{~/cs407/project/}}} directory

!! Project progress reports  (5%)
* So I can make sure you're staying on track and not waiting until the last minute
* A brief writeup that should minimally contain:
** Work completed since the proposal or previous progress report
** Work yet to be completed
** Expected milestones met and not met
** Updated timeline (if necessary)
** Any outstanding requirements
** Any encountered problems
** Any potential roadblocks to successful completion of your project.
* Save a PDF named {{File{cs407-//username//-progress//#//.pdf}}} to your {{File{~/cs407/project/}}} directory where //#// is either 1 or 2.

!! Final Deliverables & Project writeup (80%)
** Will be posted to the class website
** Targeted to your classmates
** Either a how-to doc or tutorial
*** How-to document - Information about your project and steps we can follow to implement it
*** Tutorial - Something we can learn from
** Be sure to also include:
*** Your name and the date
*** An intro paragraph explaining what your project is and accomplishes
*** A list of references
** Save a PDF named {{File{cs407-//username//-project.pdf}}}  to your {{File{~/cs407/project/}}} directory

!! Presentation (10%)
* Target time of 15-20 minutes
* Presentations will take place on or about the last day of classes
* We may not have time for everyone
* Full project credit will only be awarded to those who present
* Presentation time slots will be competitive and awarded based on project quality and utility
* Presentation schedule will be posted by April 25.
* A well written project proposal and final writeup will be useful tools for assessing the above points
* If you have presentation slides, save them to your {{File{~/cs407/project/}}} directory with a base file name of {{File{cs407-//username//-Slides}}} in a file format of your choice.

!!Project ideas

!!! Good sources:
Usenix -

!!! Some ideas:

NCS Club hackathon scoring engine
Last year a student created a scoring engine for NCS club competitions and practice sessions.  This was a well developed project and currently needs a little work to take it to the next level.  This project will cross multiple disciplines:  systems administration, programming (node.js), and virtualization.   Programming work is needed to support teams and virtualization work will be needed to better integrate with the Xen hypervisor

Linux containers 
Linux containers are a virtualization environment used to run multiple Linux systems within a single control host.  This allows applications running on that single host system to run in isolated environments.  Research linux containers, demonstrate their creation and use, and present your findings to the class.  You may need additional resources to complete this project, such as additional ~VMs or a physical host system.

~TiddlyWeb Server 
~TiddlyWiki is a self contained wiki system where all content is stored in a single HTML file.  A few students and classes on campus are currently using it.  I would like to improve our current use by incorporating the [[TiddlyWeb|]] server backend so content can be centrally managed.   Implement the ~TiddlyWiki / ~TiddlyWeb combination on your apache web server, creating a ~TiddlyWeb instance and documentation that others can easily follow to duplicate your work.

Vulnerability / security assessment scanning
There are many tools available for scanning a network for vulnerabilities or assessing the security state of a system.  We will touch on these tools only briefly in class.  Identify some possible tools and utilize them for system and network scans.  When you are more familiar with the tools we will target the CS network systems for more real-world scanning results.

Obtain password lists and leverage
It seems web sites are constantly being compromised and having lists of their user's credentials stolen and leaked to the web.  For a security researcher or systems administrator, there is useful intel to be found in these lists.  Obtain a large list of leaked passwords and find a useful leverage that data.

Covert communication channels and data exfiltration
Once a host is compromised a method needs to be identified covertly move data off of the infiltrated network.  Research covert communication channels and how they can be utilized for exfiltrating a company's data without detection.

A honeypot is a system or service designed to trap, contain, record, and observe attacks on your servers or network.  Rather the attacking a production server the attacker is communicating with the honeypot while its owner is monitoring the activity.  This data can provide useful insight to a defender into the methods and tools of their adversaries.  Once your honeypot is set up and proven safe and functional we will isolate it from the campus network and open it to the global internet for attack.  You will need additional resources for this, such as test ~VMs or physical PCs.  Your final deliverable and presentation to the class should minimally contain instructions for setting up your honeypots, a demonstration of its use, and what was learned from its data collection.

DNSSEC lookaside validation
The DNS Security extensions (DNSSEC) provide provable validation of our DNS records based on a chain of trust.  Validity of the DNS records cannot be proven if one link in that chain is broken.  DNSSEC lookaside validation may provide a means to properly validate DNS sub domains if a parent domain is not providing secure DNS zones.  Determine what is required to provide proper lookaside validation, whether it is actually feasible, and if so implement.  You will be provided a DNS sub-domain to secure with DNSSEC.

Improve antispam meaures
Blocking junk email is a continual arms race between the mail admins and the spammers.  Identify and develop current strategies for blocking junk mail and implement them in your VM environment.  Your list of tools should include DKIM and spf.  Once implemented in development we can look at testing your project on a live mail server.

Customizing the Linux kernel
For the purposes of this class, we will be using a stock kernel maintained and distributed by ~CentOS.  Occasionally an administrator required features or drivers not built into the default kernel.  We will not have enough time to cover this in detail in class.  Identify a reason to customize the kernel and walk through the process of configuration, compile, installation, and activation in the grub configuration.

Web security
Web servers by their nature need to be globally exposed.  Their large exposure makes them easy targets for abuse.  Research, develop and implement strategies for protecting your web server from attackers.  If your project is successful we will look at implementing it on a live system for further testing.

Web log analysis
A high level analysis of log files can provide useful insight into what is happening on a system or network and identify problems or malicious activity.  Implement a system which analyzing web server logs and present that information to the administrators in a useful way.  Particular focus should be on identifying security related events.  Live log data will be provided once you have a plan/system in place for using it.





A cool Raspberry Pi project 


|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Author:|Simon Baird <>|
config.quickOpenTag = {

	dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?

	createTagButton: function(place,tag,excludeTiddler) {
		// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
		var splitTag = tag.split("|");
		var pretty = tag;
		if (splitTag.length == 2) {
			tag = splitTag[1];
			pretty = splitTag[0];

		var sp = createTiddlyElement(place,"span",null,"quickopentag");

		var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
		if (excludeTiddler)

	miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var tagged = store.getTaggedTiddlers(tiddler.title);
		if (tagged.length > 0) {
			var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
			theTag.className = "miniTag";

	allTagsHandler: function(place,macroName,params) {
		var tags = store.getTags(params[0]);
		var filter = params[1]; // new feature
		var ul = createTiddlyElement(place,"ul");
		if(tags.length == 0)
		for(var t=0; t<tags.length; t++) {
			var title = tags[t][0];
			if (!filter || (title.match(new RegExp('^'+filter)))) {
				var info = getTiddlyLinkInfo(title);
				var theListItem =createTiddlyElement(ul,"li");
				var theLink = createTiddlyLink(theListItem,tags[t][0],true);
				var theCount = " (" + tags[t][1] + ")";
				var theDropDownBtn = createTiddlyButton(theListItem," " +

	// todo fix these up a bit
	styles: [
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
"	{ margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
"	{ border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
"	{ margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
"	{ margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
"	/* looks better in right justified main menus */",
"	{ margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }",
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",

	init: function() {
		// we fully replace these builtins. can't hijack them easily
		window.createTagButton = this.createTagButton;
		config.macros.allTags.handler = this.allTagsHandler;
		config.macros.miniTag = { handler: this.miniTagHandler };
		config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;



| !Symbol | !Meaning | !Escape | !Not supported by |
| ^ |Start of line| | |
| $ |End of line| | |
| [ ] |Character Classes (match any one character listed) | | |
|~|Characters may be specified singly or in ranges| | |
| [^ ] |Negated character class (match any one character not listed| | |
| ? |Optional item.  Match 0 or 1. | | sed |
| ( ) |Alternation (match any one of the sub-expressions)| | |
|~|Grouping| | |
|~|Capture backreference Access with \//n//| * | |
| {{{|}}} |Or.  Match either expression it separates.  Use with ( )| | |
| . |Any single character| | |
| + |Repetition:  1 or more. | | sed |
| * |Repetition: 0 or more| | |
| { } |Defined range of matches (bounds) {//min//,//max//} or {//min//,} or {//exactly//}| * | |
| \ |Suppress normal behavior of a metacharacter| | |
|~|Access a backreference:  \//n//| | |
| \< |Match start of word.| * | bsd sed |
| \> |Match end of word.| * | bsd sed |

| !Symbol | !File Globbing   | !Regex | !Regex Equivalent |
| ? |Exactly 1|0 or 1| . |
| { } |Sets|# of matches| ( ) |
|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0 ($Rev: 5501 $)|
|Date:|$Date: 2008-06-10 23:11:55 +1000 (Tue, 10 Jun 2008) $|
|Author:|Simon Baird <>|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
config.renameTags = {

	prompts: {
		rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
		remove: "Remove the tag '%0' from %1 tidder%2?"

	removeTag: function(tag,tiddlers) {
		for (var i=0;i<tiddlers.length;i++) {

	renameTag: function(oldTag,newTag,tiddlers) {
		for (var i=0;i<tiddlers.length;i++) {
			store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
			store.setTiddlerTag(tiddlers[i].title,true,newTag);  // add new

	storeMethods: {

		saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,

		saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
			if (title != newTitle) {
				var tagged = this.getTaggedTiddlers(title);
				if (tagged.length > 0) {
					// then we are renaming a tag
					if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))

					if (!this.tiddlerExists(title) && newBody == "")
						// dont create unwanted tiddler
						return null;
			return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);

		removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,

		removeTiddler: function(title) {
			var tagged = this.getTaggedTiddlers(title);
			if (tagged.length > 0)
				if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
			return this.removeTiddler_orig_renameTags(title);


	init: function() {



Type the text for 'Resources'
<<toggleSideBar "" "Toggle Sidebar" hide>>
Unless you are already familiar with the material we are covering, properly completing lab assignments on time is necessary to receive a good grade for this course.  Not competing lab assignments at all will likely result in a failing grade.  Our lab exercises are only the minimum.  Competency in this subject material is found only with practice.  

Standard late lab point reductions:
*10% - submitted late but on the due date
*20% - submitted after due date
*30% - submitted after I grade lab assignment
*40% - submitted after graded labs are returned.
*50% - submitted after returned labs are reviewed in class.


!!!Extra Credit
There will be ample opportunities for extra credit throughout the semester.  Extra credit opportunities make it possible to score over 100% on each test or for a final lab average.
*Class participation minor level boost to final grade.
*Extra credit points towards lab average for completing all labs.  (Extra credit awarded is based on overall quality of lab work)
*Extra credit questions on each test

Ample opportunities for extra credit makes curving unnecessary.

Letter grades will be assigned as follows:

| !Percent | !Grade |
| 95% ≥ | A |
| 90% ≥ | A- |
| 87% ≥ | B+ |
| 84% ≥ | B |
| 79% ≥ | B- |
| 77% ≥ | C+ |
| 74% ≥ | C |
| 69% ≥ | C- |
| 67% ≥ | D+ |
| 63% ≥ | D |
| ≤ 62% | F |

A final grade of A+ may be awarded to students who meet one of the following criteria:
1) Final percentage over 100% and point leader for the semester, or
2) Final percentage over 98%, no missing or late labs, and awarded class participation credit.

Attendance will be recorded, but not used for grading.  However, class participation points cannot be earned if you do not attend classes.  Sufficient class participation points will result in a minor level boost to your final grade.  ex:  B becomes B+

*Shell scripting quick reference:
*Awk one liners:
*Sed one liners:
<<search>><<closeAll>><<collapseAll>><<expandAll>><<permaview>><<newTiddler>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">><<slider chkSliderContents [[TabContents]] 'contents »' 'contents'>>

#sidebar {
 color: #000;
 background: transparent;

#sidebarOptions {
 background: #fff;

#sidebarOptions .button {
 color: #999;

#sidebarOptions .button:hover {
 color: #000;
 background: #fff;

#sidebarOptions .button:active {
 color: #000;
 background: #fff;

#sidebarOptions .sliderPanel {
 background: transparent;

#sidebarOptions .sliderPanel A:hover {
 color: #000;
 background: #fff;

#sidebarOptions .sliderPanel A:active {
 color: #000;
 background: #fff;

.sidebarSubHeading {
 color: #000;

#sidebarOptions .sliderPanel .tabSelected{
  border: 1px solid #ccc;
  background-color: #fff;
  margin: 0px;
  padding-top: 5px;
  padding-bottom: 0px;
  padding-left: 2px;
  padding-right: 2px;
  -moz-border-radius-topleft: 1em;
  -moz-border-radius-topright: 1em;}

#sidebarOptions .sliderPanel .tabUnselected{
  border:    1px solid #ccc;
  background-color: #eee;
  margin: 0px;
  padding-top: 5px;
  padding-bottom: 0px;
  padding-left: 2px;
  padding-right: 2px;
  -moz-border-radius-topleft: 1em;
  -moz-border-radius-topright: 1em;}

#sidebarTabs .tabContents .tiddlyLink:hover {
 background: #fff;
 color: #000;

#sidebarTabs .tabContents {
 color: #000;

#sidebarTabs .button {
 color: #666;
  border-top:    1px solid #ccc;
  border-left:   1px solid #ccc;
  border-bottom: 2px solid #ccc;
  border-right:  2px solid #ccc;

#sidebarTabs .tabContents .button:hover {
 color: #000;
 background: #fff;

.tagging, .tagged {
  padding: 0.5em;
  background-color: #eee;
  border-top:    1px solid #ccc;
  border-left:   1px solid #ccc;
  border-bottom: 3px solid #ccc;
  border-right:  3px solid #ccc;
  -moz-border-radius: 1em; }


Spring 2015 Course Notes
UNIX System Administration - SUNYIT CS 407


body {
  background: #eee; }

h1 {font-size:2.0em; }
h2 { color: #000; background: transparent; text-decoration: underline; }
h3 { margin: 0.0em; color: #000; background: transparent; }
h4,h5 { color: #000; background: transparent; }

h1 {
        margin: 4px 0 4px 0;
	padding: 5px;
	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::PrimaryPale]];

ul {
	margin-top: 0;
	margin-bottom: 0;

.headerShadow {
  padding: 1.0em; }

.headerForeground {
  padding: 1.0em; }

.selected .tagging, .selected .tagged {
  padding: 0.5em;
  background-color: #eee;
  border-top:    1px solid #ccc;
  border-left:   1px solid #ccc;
  border-bottom: 3px solid #ccc;
  border-right:  3px solid #ccc;
  -moz-border-radius: 1em; }

.shadow .title {
  color: #999; }

.siteTitle {
  font-size: 2.5em; }

.siteSubtitle {
  font-size: 1.0em; }

.subtitle {
	font-size: 0.8em;

.tagging, .tagged {
  padding: 0.5em;
  background-color: #eee;
  border-top:    1px solid #ccc;
  border-left:   1px solid #ccc;
  border-bottom: 3px solid #ccc;
  border-right:  3px solid #ccc;
  -moz-border-radius: 1em; }

.tiddler {
  border-top:    1px solid #ccc;
  border-left:   1px solid #ccc;
  border-bottom: 3px solid #ccc;
  border-right:  3px solid #ccc;
  margin: 0.5em;
  padding: 0.5em;
  -moz-border-radius: 1em; }

.title {
  font-size: 1.5em; }

  padding-top: 0.0em;
  padding-left: 0.5em;
  padding-right: 0.5em;
  -moz-border-radius-topleft: 0.5em;
  -moz-border-radius-topright: 0.5em;}

.tabUnselected {
  padding-top: 0.0em;
  padding-left: 0.5em;
  padding-right: 0.5em;
  -moz-border-radius-topleft: 0.5em;
  -moz-border-radius-topright: 0.5em;}

.tabContents {
  margin: 0px;
  padding-top: 0px;
  padding-bottom: 0px;
  padding-left: 2px;
  padding-right: 2px;
  -moz-border-radius: 1em; }

.viewer .listTitle {
  list-style-type: none;

.viewer pre {
  background-color: #f8f8ff;
  border-color: #ddf; }

#messageArea { background-color:#bde; border-color:#8ab; border-width:4px; border-style:dotted; font-size:90%; }
#messageArea .button { text-decoration:none; font-weight:bold; background:transparent; border:0px; }
#messageArea .button:hover {background: #acd;}

.Command{color: fuchsia;font-size: 10pt;font-family: Courier, monospace;margin-left: 2px;margin-right: 2px;}
.Commandi{color: fuchsia;font-size: 10pt;font-family: Courier, monospace;margin-left: 20px;margin-right: 2px;}
.File{color: #4c7fbc;font-size: 10pt;font-family: Courier, monospace;margin-left: 2px;margin-right: 2px; font-weight:bold;}
.Remove{background-color: orange}
.Host{color: #0f9791;font-size: 10pt;font-family: Courier, monospace;margin-left: 2px;margin-right: 2px; font-weight:bold;}

 .HideSideBarButton {margin-left: 3em;}

.viewer div.centeredTable {
	text-align: center;

.viewer div.centeredTable table {
	margin: 0 auto;
	text-align: left;

.viewer table.borderless,
.viewer table.borderless * {
	border: 0;
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::PrimaryLight]];} */
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
body {
	background: [[ColorPalette::Background]];
	color: [[ColorPalette::Foreground]];

	color: [[ColorPalette::PrimaryMid]];

	background: [[ColorPalette::PrimaryMid]];
	color: [[ColorPalette::Background]];

a img{
	border: 0;

h1,h2,h3,h4,h5 {
	color: [[ColorPalette::SecondaryDark]];
	background: [[ColorPalette::PrimaryPale]];

.button {
	color: [[ColorPalette::PrimaryDark]];
	border: 1px solid [[ColorPalette::Background]];

.button:hover {
	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::SecondaryLight]];
	border-color: [[ColorPalette::SecondaryMid]];

.button:active {
	color: [[ColorPalette::Background]];
	background: [[ColorPalette::SecondaryMid]];
	border: 1px solid [[ColorPalette::SecondaryDark]];

.header {
	background: [[ColorPalette::PrimaryMid]];

.headerShadow {
	color: [[ColorPalette::Foreground]];

.headerShadow a {
	font-weight: normal;
	color: [[ColorPalette::Foreground]];

.headerForeground {
	color: [[ColorPalette::Background]];

.headerForeground a {
	font-weight: normal;
	color: [[ColorPalette::PrimaryPale]];

	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::TertiaryPale]];
	border-left: 1px solid [[ColorPalette::TertiaryLight]];
	border-top: 1px solid [[ColorPalette::TertiaryLight]];
	border-right: 1px solid [[ColorPalette::TertiaryLight]];

.tabUnselected {
	color: [[ColorPalette::Background]];
	background: [[ColorPalette::TertiaryMid]];

.tabContents {
	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::TertiaryPale]];
	border: 1px solid [[ColorPalette::TertiaryLight]];

.tabContents .button {
	 border: 0;}

#sidebar {

#sidebarOptions input {
	border: 1px solid [[ColorPalette::PrimaryMid]];

#sidebarOptions .sliderPanel {
	background: [[ColorPalette::PrimaryPale]];

#sidebarOptions .sliderPanel a {
	border: none;
	color: [[ColorPalette::PrimaryMid]];

#sidebarOptions .sliderPanel a:hover {
	color: [[ColorPalette::Background]];
	background: [[ColorPalette::PrimaryMid]];

#sidebarOptions .sliderPanel a:active {
	color: [[ColorPalette::PrimaryMid]];
	background: [[ColorPalette::Background]];

.wizard {
	background: [[ColorPalette::SecondaryLight]];
	border-top: 1px solid [[ColorPalette::SecondaryMid]];
	border-left: 1px solid [[ColorPalette::SecondaryMid]];

.wizard h1 {
	color: [[ColorPalette::SecondaryDark]];

.wizard h2 {
	color: [[ColorPalette::Foreground]];

.wizardStep {
	background: [[ColorPalette::Background]];
	border-top: 1px solid [[ColorPalette::SecondaryMid]];
	border-bottom: 1px solid [[ColorPalette::SecondaryMid]];
	border-left: 1px solid [[ColorPalette::SecondaryMid]];

.wizard .button {
	color: [[ColorPalette::Background]];
	background: [[ColorPalette::PrimaryMid]];
	border-top: 1px solid [[ColorPalette::PrimaryLight]];
	border-right: 1px solid [[ColorPalette::PrimaryDark]];
	border-bottom: 1px solid [[ColorPalette::PrimaryDark]];
	border-left: 1px solid [[ColorPalette::PrimaryLight]];

.wizard .button:hover {
	color: [[ColorPalette::PrimaryLight]];
	background: [[ColorPalette::PrimaryDark]];
	border-color: [[ColorPalette::PrimaryLight]];

.wizard .button:active {
	color: [[ColorPalette::Background]];
	background: [[ColorPalette::PrimaryMid]];
	border-top: 1px solid [[ColorPalette::PrimaryLight]];
	border-right: 1px solid [[ColorPalette::PrimaryDark]];
	border-bottom: 1px solid [[ColorPalette::PrimaryDark]];
	border-left: 1px solid [[ColorPalette::PrimaryLight]];

#messageArea {
	border: 1px solid [[ColorPalette::SecondaryDark]];
	background: [[ColorPalette::SecondaryMid]];
	color: [[ColorPalette::PrimaryDark]];

#messageArea .button {
	padding: 0.2em 0.2em 0.2em 0.2em;
	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::Background]];

.popup {
	background: [[ColorPalette::PrimaryLight]];
	border: 1px solid [[ColorPalette::PrimaryMid]];

.popup hr {
	color: [[ColorPalette::PrimaryDark]];
	background: [[ColorPalette::PrimaryDark]];
	border-bottom: 1px;

.popup li.disabled {
	color: [[ColorPalette::PrimaryMid]];

.popup li a, .popup li a:visited {
	color: [[ColorPalette::TertiaryPale]];
	border: none;

.popup li a:hover {
	background: [[ColorPalette::PrimaryDark]];
	color: [[ColorPalette::Background]];
	border: none;

.tiddler .defaultCommand {
 font-weight: bold;

.shadow .title {
	color: [[ColorPalette::TertiaryDark]];

.title {
	color: [[ColorPalette::SecondaryDark]];

.subtitle {
	color: [[ColorPalette::TertiaryDark]];

.toolbar {
	color: [[ColorPalette::PrimaryMid]];

.tagging, .tagged {
	border: 1px solid [[ColorPalette::TertiaryPale]];
	background-color: [[ColorPalette::TertiaryPale]];

.selected .tagging, .selected .tagged {
	background-color: [[ColorPalette::TertiaryLight]];
	border: 1px solid [[ColorPalette::TertiaryMid]];

.tagging .listTitle, .tagged .listTitle {
	color: [[ColorPalette::PrimaryDark]];

.tagging .button, .tagged .button {
		border: none;

.footer {
	color: [[ColorPalette::TertiaryLight]];

.selected .footer {
	color: [[ColorPalette::TertiaryMid]];

.sparkline {
	background: [[ColorPalette::PrimaryPale]];
	border: 0;

.sparktick {
	background: [[ColorPalette::PrimaryDark]];

.error, .errorButton {
	color: [[ColorPalette::Foreground]];
	background: [[ColorPalette::Error]];

.warning {
	color: [[ColorPalette::Foreground]];
	background: [[ColorPalette::SecondaryPale]];

.cascade {
	background: [[ColorPalette::TertiaryPale]];
	color: [[ColorPalette::TertiaryMid]];
	border: 1px solid [[ColorPalette::TertiaryMid]];

.imageLink, #displayArea .imageLink {
	background: transparent;

.viewer .listTitle {list-style-type: none; margin-left: -2em;}

.viewer .button {
	border: 1px solid [[ColorPalette::SecondaryMid]];

.viewer blockquote {
	border-left: 3px solid [[ColorPalette::TertiaryDark]];

.viewer table {
	border: 2px solid [[ColorPalette::TertiaryDark]];

.viewer th, thead td {
	background: [[ColorPalette::SecondaryMid]];
	border: 1px solid [[ColorPalette::TertiaryDark]];
	color: [[ColorPalette::Background]];

.viewer td, .viewer tr {
	border: 1px solid [[ColorPalette::TertiaryDark]];

.viewer pre {
	border: 1px solid [[ColorPalette::SecondaryLight]];
	background: [[ColorPalette::SecondaryPale]];

.viewer code {
	color: [[ColorPalette::SecondaryDark]];

.viewer hr {
	border: 0;
	border-top: dashed 1px [[ColorPalette::TertiaryDark]];
	color: [[ColorPalette::TertiaryDark]];

.highlight, .marked {
	background: [[ColorPalette::SecondaryLight]];

.editor input {
	border: 1px solid [[ColorPalette::PrimaryMid]];

.editor textarea {
	border: 1px solid [[ColorPalette::PrimaryMid]];
	width: 100%;

.editorFooter {
	color: [[ColorPalette::TertiaryMid]];

* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
!Sections in this Tiddler:
*Generic rules
**Links styles
**Link Exceptions
*Main menu
**Sidebar options
**Sidebar tabs
*Message area
*Tiddler display
*Misc. rules
!Generic Rules /%==============================================%/
body {
	font-size: .75em;
	font-family: arial,helvetica;
	position: relative;
	margin: 0;
	padding: 0;

h1,h2,h3,h4,h5 {
	font-weight: bold;
	text-decoration: none;
	padding-left: 0.4em;

h1 {font-size: 1.5em;}
h2 {font-size: 1.25em;}
h3 {font-size: 1.1em;}
h4 {font-size: 1em;}
h5 {font-size: .9em;}

hr {
	height: 1px;

	text-decoration: none;

ol { list-style-type: decimal }
ol ol { list-style-type: lower-alpha }
ol ol ol { list-style-type: lower-roman }
ol ol ol ol { list-style-type: decimal }
ol ol ol ol ol { list-style-type: lower-alpha }
ol ol ol ol ol ol { list-style-type: lower-roman }
ol ol ol ol ol ol ol { list-style-type: decimal }
''General Link Styles'' /%-----------------------------------------------------------------------------%/
.externalLink {
	text-decoration: underline;

/* the 'a' is required for IE, otherwise it renders the whole tiddler a bold */
a.tiddlyLinkNonExisting.shadow {
	font-weight: bold;
''Exceptions to common link styles'' /%------------------------------------------------------------------%/

#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkExisting,
#sidebarTabs .tiddlyLinkNonExisting{
 font-weight: normal;
 font-style: normal;

!Header /%==================================================%/

.header {
		position: relative;

.header a:hover {
	background: transparent;

.headerShadow {
	position: relative;
	padding: 4.5em 0em 1em 1em;
	left: -1px;
	top: -1px;

.headerForeground {
	position: absolute;
	padding: 4.5em 0em 1em 1em;
	left: 0px;
	top: 0px;

.siteTitle {
	font-size: 3em;

.siteSubtitle {
	font-size: 1.2em;
	padding: 0em 0em 0em 2em;

!Main menu /%==================================================%/
#mainMenu {
	position: absolute;
	left: 0;
	width: 10em;
	text-align: right;
	line-height: 1.6em;
	padding: 1.5em 0.5em 0.5em 0.5em;
	font-size: 1.1em;

!Sidebar rules /%==================================================%/
#sidebar {
	position: absolute;
	right: 3px;
	width: 16em;
	font-size: .9em;
''Sidebar options'' /%----------------------------------------------------------------------------------%/
#sidebarOptions {
	padding-top: 0.3em;

#sidebarOptions a {
	margin: 0em 0.2em;
	padding: 0.2em 0.3em;
	display: block;

#sidebarOptions input {
	margin: 0.4em 0.5em;

#sidebarOptions .sliderPanel {
	margin-left: 1em;
	padding: 0.5em;
	font-size: .85em;

#sidebarOptions .sliderPanel a {
	font-weight: bold;
	display: inline;
	padding: 0;

#sidebarOptions .sliderPanel input {
	margin: 0 0 .3em 0;
''Sidebar tabs'' /%-------------------------------------------------------------------------------------%/

#sidebarTabs .tabContents {
	width: 15em;
	overflow: hidden;

!Message area /%==================================================%/
#messageArea {
position:absolute; top:0; right:0; margin: 0.5em; padding: 0.5em;

*[id='messageArea'] {
position:fixed !important; z-index:99;}

.messageToolbar {
display: block;
text-align: right;

#messageArea a{
	text-decoration: underline;
!Popup /%==================================================%/
.popup {
	font-size: .9em;
	padding: 0.2em;
	list-style: none;
	margin: 0;

.popup hr {
	display: block;
	height: 1px;
	width: auto;
	padding: 0;
	margin: 0.2em 0em;

.popup li.disabled {
	padding: 0.2em;

.popup li a{
	display: block;
	padding: 0.2em;
!Tabs /%==================================================%/
.tabset {
	padding: 1em 0em 0em 0.5em;

.tab {
	margin: 0em 0em 0em 0.25em;
	padding: 2px;

.tabContents {
	padding: 0.5em;

.tabContents ul, .tabContents ol {
	margin: 0;
	padding: 0;

.txtMainTab .tabContents li {
	list-style: none;

.tabContents li.listLink {
	 margin-left: .75em;
!Tiddler display rules /%==================================================%/
#displayArea {
	margin: 1em 17em 0em 14em;

.toolbar {
	text-align: right;
	font-size: .9em;
	visibility: hidden;

.selected .toolbar {
	visibility: visible;

.tiddler {
	padding: 1em 1em 0em 1em;

.missing .viewer,.missing .title {
	font-style: italic;

.title {
	font-size: 1.6em;
	font-weight: bold;

.missing .subtitle {
 display: none;

.subtitle {
	font-size: 0.8em;

/* I'm not a fan of how button looks in tiddlers... */
.tiddler .button {
	padding: 0.2em 0.4em;

.tagging {
margin: 0.5em 0.5em 0.5em 0;
float: left;
display: none;

.isTag .tagging {
display: block;

.tagged {
margin: 0.5em;
float: right;

.tagging, .tagged {
font-size: 0.9em;
padding: 0.25em;

.tagging ul, .tagged ul {
list-style: none;margin: 0.25em;
padding: 0;

.tagClear {
clear: both;

.footer {
	font-size: .9em;

.footer li {
display: inline;
''The viewer is where the tiddler content is displayed'' /%------------------------------------------------%/
* html .viewer pre {
	width: 99%;
	padding: 0 0 1em 0;

.viewer {
	line-height: 1.4em;
	padding-top: 0.5em;

.viewer .button {
	margin: 0em 0.25em;
	padding: 0em 0.25em;

.viewer blockquote {
	line-height: 1.5em;
	padding-left: 0.8em;
	margin-left: 2.5em;

.viewer ul, .viewer ol{
	margin-left: 0.5em;
	padding-left: 1.5em;

.viewer table {
	border-collapse: collapse;
	margin: 0.8em 1.0em;

.viewer th, .viewer td, .viewer tr,.viewer caption{
	padding: 3px;

.viewer pre {
	padding: 0.5em;
	margin-left: 0.5em;
	font-size: 1.2em;
	line-height: 1.4em;
	overflow: auto;

.viewer code {
	font-size: 1.2em;
	line-height: 1.4em;
''The editor replaces the viewer in the tiddler'' /%------------------------------------------------%/
.editor {
font-size: 1.1em;

.editor input, .editor textarea {
	display: block;
	width: 100%;
	font: inherit;

.editorFooter {
	padding: 0.25em 0em;
	font-size: .9em;

.editorFooter .button {
padding-top: 0px; padding-bottom: 0px;}

.fieldsetFix {border: 0;
padding: 0;
margin: 1px 0px 1px 0px;
!Misc rules /%==================================================%/
.sparkline {
	line-height: 1em;

.sparktick {
	outline: 0;

.zoomer {
	font-size: 1.1em;
	position: absolute;
	padding: 1em;

.cascade {
	font-size: 1.1em;
	position: absolute;
	overflow: hidden;
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea, #toolbar, #topMenu, #rightMenu {display: none !important;}
#header, #headerShadow {display: none !important;}
.siteSubtitle {display: none !important;}

.siteTitle { font-size: 1.5em; }

#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox where print preview displays the noscript content */
Type the text for 'Styles'
<<tabs txtMainTab Timeline Timeline TabTimeline All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>
The following command table should prove useful for this course.  This is not an extensive list of commands you will need to know / become familiar with.

| !&nbsp;Cover&nbsp; | !&nbsp;Command&nbsp; | !Description |
|>|>|bgcolor(#a0ffa0): ''Basic Commands'' |
| x | echo |output command arguments to the terminal|
| x | cd |change directories|
| x | pwd |display current working directory|
| x | ls |list files|
| x | cp |copy files|
| x | rm |remove files|
| x | mv |move files|
| x | mkdir |create directory|
| x | rmdir |remove directory|
| x | touch |create an empty file with default permissions|
| x | ln |create link|
| x | man |view man pages|
| x | chmod |set permissions for a file|
|  | chgrp |set group for a file|
|>|>|bgcolor(#a0ffa0): ''Display Text / Editors'' |
| x | less |display text output one page at a time|
|  | pico |easy to use text editor|
|  | nano |GNU clone of pico|
| x | vi |advanced unix text editor|
|  | ex |line oriented version of vi|
|  | vim |vi improved|
| x | vimtutor |learn how to use the vim editor|
|>|>|bgcolor(#a0ffa0): ''Filters'' |
| x | cat |concatenate and print files|
| x | grep |pattern matching filter|
| x | egrep |extended regular expression pattern matching filter|
| x | head |display first lines of a file|
| x | tail |display the last part of a file|
| x | cut |cut out selected portions of each line of a file|
| x | fold |fold long lines for finite width output device|
| x | sort |sort lines of text files|
| x | uniq |report or filter out repeated lines in a file|
| x | wc |word, line, character, and byte count|
| x | tr |translate characters|
|  | paste |merge lines of input|
|  | nl |line numbering filter|
| x | sed |stream editor|
| x | awk |pattern-directed scanning and processing language|
| x | tee |duplicate standard input to a file|
|  | strings |print the strings of printable characters in (binary) files|
|  | cmp |compare two files|
|  | diff |compare files line by line|
|  | comm |select or reject lines common to two files|
|>|>|bgcolor(#a0ffa0): ''System Commands'' |
| x | script |save copy of terminal session|
|  | source |read a .file|
| x | rehash |recompute hash table of where commands are located|
| x | which |scan path for a program and return its location (or definition of an alias)|
| x | df |display free disk space|
| x | du |disk usage (-s display each file, -k 1K blocks , -h = human readable|
| x | find |walk a file hierarchy in search of files|
|  | locate |find filenames quickly based on pre-generated file database|
|  | hostname |print name of current host system|
| x | uptime |show how long system has been running|
| x | uname |display information about the system|
|  | xargs |construct argument list(s) and execute utility|
|  | quota |display disk usage and limits|
|  | crontab |schedule commands for automated execution on regular intervals|
|  | at |schedule a job for later execution|
|>|>|bgcolor(#a0ffa0): ''Process Management / Job Control'' |
| x | ps |process status|
| x | top |display and update information about the top cpu processes|
| x | kill |terminate or signal a process|
| x | jobs |display all jobs|
| x | fg |continue background jobs in the foreground|
| x | bg |continue suspended job in the background|
| x | stop |suspend job running in the background|
|  | suspend |suspend the current running shell|
|>|>|bgcolor(#a0ffa0): ''User Information'' |
| x | w |display who is logged in and what they are doing|
| x | id |return user identity|
| x | groups |show group memberships|
|  | users |list usernames of current logged in users|
|  | who |display who is on the system|
|  | whoami |display effective user id|
| x | finger |user information lookup program|
| x | last |indicate last logins of users and ttys|
|>|>|bgcolor(#a0ffa0): ''Misc commands useful for shell scripting'' |
| x | clear |clear the screen|
| x | read //var// |prompt the user to enter information, saving to //var//|
| x | date |display the current date and time with optional formatting.  see strftime manpage|
| x | test |condition evaluation utility.  Linked to [  See test manpage.|
| x | expr |evaluate an expression|
| x | jot |print sequential or random numbers|
|  | sleep //n// |pause execution for //n// seconds|
|  | stat |display extended file status/information|
|  | stty |set the options for a terminal device interface|
|  | basename |return the file name portion of a path|
|  | dirname |return the directory name portion of a path|
|  | fstat |List open files or determine whether specified file is open|
| x | exit [//n//] |log out or quit a script with the option exit status of //n//|
|>|>|bgcolor(#a0ffa0): ''Networking / Communication'' |
| x | ssh |~OpenSSH SSH client|
| x | scp |secure copy (remote file copy program)|
|  | rsync |a fast, versatile, remote (and local) file-copying tool|
|  | telnet |user interface to the TELNET protocol.  also useful for testing connectivity to arbitrary ports|
|  | talk / ytalk |talk to another user|
|  | write |send a message to another user|
|  | mesg |display (do not display) messages from other users|
|  | host |DNS lookup utility|
|  | nslookup |query Internet name servers interactively|
|  | traceroute |print the route packets take to network host|
|  | ping |send ICMP ~ECHO_REQUEST packets to network hosts|
|  | lynx / links |character mode WWW browser|
|>|>|bgcolor(#a0ffa0): ''Text Formatting & Printing'' |
| x | lpr |command line print utility|
| x | lpq |print spool queue examination program|
| x | lprm |remove jobs from the line printer spooling queue|
| x | pdf2ps |Ghostscript PDF to ~PostScript translator|
| x | a2ps |format files for printing on a ~PostScript printer|
|>|>|bgcolor(#a0ffa0): ''Working with files'' |
| x | file |display file type|
| x | tar |manipulate file archive files|
| x | gzip |compression tool using ~Lempel-Ziv coding|
| x | gunzip |decompression tool using ~Lempel-Ziv coding|
| x | bzip2 |a block-sorting file compressor|
| x | bunzip2 |a block-sorting file decompressor|
|  | split |split a file into pieces|
| x | md5 / md5sum |calculate a message-digest fingerprint (checksum) for a file (freebsd / linux)|
|  | srm |securely remove files or directories|
|  | rsync |a fast, versatile, remote (and local) file-copying tool|
|Created by|SimonBaird|
|Version|1.1.2 25-Apr-06|
|Requires|See TagglyTagging|

* 1.1.2 (25-Apr-2006) embedded TagglyTaggingStyles. No longer need separated tiddler for styles.
* 1.1.1 (6-Mar-2006) fixed bug with refreshAllVisible closing tiddlers being edited. Thanks Luke Blanshard.


!Setup and config

version.extensions.TagglyListPlugin = {
	major: 1, minor: 1, revision: 2,
	date: new Date(2006,4,25),
	source: ""

config.macros.tagglyList = {};
config.macros.tagglyListByTag = {};
config.macros.tagglyListControl = {};
config.macros.tagglyListWithSort = {};
config.macros.hideSomeTags = {};

// change this to your preference
config.macros.tagglyListWithSort.maxCols = 6;

config.macros.tagglyList.label = "Tagged as %0:";

// the default sort options. set these to your preference
config.macros.tagglyListWithSort.defaults = {
 sortBy:"title", // title|created|modified
 sortOrder: "asc", // asc|desc
 hideState: "show", // show|hide
 groupState: "nogroup", // nogroup|group
 numCols: 1

// these tags will be ignored by the grouped view
config.macros.tagglyListByTag.excludeTheseTags = [

config.macros.tagglyListControl.tags = {
 modified: "sortByModified",
 created: "sortByCreated",

// note: should match config.macros.tagglyListControl.tags
config.macros.hideSomeTags.tagsToHide = [


// from Eric
function isTagged(title,tag) {
 var t=store.getTiddler(title); if (!t) return false;
 return (t.tags.find(tag)!=null);

// from Eric
function toggleTag(title,tag) {
 var t=store.getTiddler(title); if (!t || !t.tags) return;
 if (t.tags.find(tag)==null) t.tags.push(tag);
 else t.tags.splice(t.tags.find(tag),1);

function addTag(title,tag) {
 var t=store.getTiddler(title); if (!t || !t.tags) return;

function removeTag(title,tag) {
 var t=store.getTiddler(title); if (!t || !t.tags) return;
 if (t.tags.find(tag)!=null) t.tags.splice(t.tags.find(tag),1);

// from Udo
Array.prototype.indexOf = function(item) {
 for (var i = 0; i < this.length; i++) {
 if (this[i] == item) {
 return i;
 return -1;
Array.prototype.contains = function(item) {
 return (this.indexOf(item) >= 0);

displays a list of tagged tiddlers.
parameters are sortField and sortOrder

// not used at the moment...
function sortedListOfOtherTags(tiddler,thisTag) {
 var list = tiddler.tags.concat(); // so we are working on a clone..
 for (var i=0;i<config.macros.hideSomeTags.tagsToHide.length;i++) {
 if (list.find(config.macros.hideSomeTags.tagsToHide[i]) != null)
 list.splice(list.find(config.macros.hideSomeTags.tagsToHide[i]),1); // remove hidden ones
 for (var i=0;i<config.macros.tagglyListByTag.excludeTheseTags.length;i++) {
 if (list.find(config.macros.tagglyListByTag.excludeTheseTags[i]) != null)
 list.splice(list.find(config.macros.tagglyListByTag.excludeTheseTags[i]),1); // remove excluded ones
 list.splice(list.find(thisTag),1); // remove thisTag
 return '[[' + list.sort().join("]] [[") + ']]';

function sortHelper(a,b) {
 if (a == b) return 0;
 else if (a < b) return -1;
 else return +1;

config.macros.tagglyListByTag.handler = function (place,macroName,params,wikifier,paramString,tiddler) {

 var sortBy = params[0] ? params[0] : "title";
 var sortOrder = params[1] ? params[1] : "asc";

 var result = store.getTaggedTiddlers(tiddler.title,sortBy);

 if (sortOrder == "desc")
 result = result.reverse();

 var leftOvers = []
 for (var i=0;i<result.length;i++) {

 var allTagsHolder = {};
 for (var i=0;i<result.length;i++) {
 for (var j=0;j<result[i].tags.length;j++) {

 if (
 result[i].tags[j] != tiddler.title // not this tiddler
 && config.macros.hideSomeTags.tagsToHide.find(result[i].tags[j]) == null // not a hidden one
 && config.macros.tagglyListByTag.excludeTheseTags.find(result[i].tags[j]) == null // not excluded
 ) {
 if (!allTagsHolder[result[i].tags[j]])
 allTagsHolder[result[i].tags[j]] = "";
 allTagsHolder[result[i].tags[j]] += "**[["+result[i].title+"]]\n";

 if (leftOvers.find(result[i].title) != null)
 leftOvers.splice(leftOvers.find(result[i].title),1); // remove from leftovers. at the end it will contain the leftovers...

 var allTags = [];
 for (var t in allTagsHolder)

 allTags.sort(function(a,b) {
 var tidA = store.getTiddler(a);
 var tidB = store.getTiddler(b);
 if (sortBy == "title") return sortHelper(a,b);
 else if (!tidA && !tidB) return 0;
 else if (!tidA) return -1;
 else if (!tidB) return +1;
 else return sortHelper(tidA[sortBy],tidB[sortBy]);

 var markup = "";

 if (sortOrder == "desc") {
 else {
 // leftovers first...
 for (var i=0;i<leftOvers.length;i++)
 markup += "*[["+leftOvers[i]+"]]\n";

 for (var i=0;i<allTags.length;i++)
 markup += "*[["+allTags[i]+"]]\n" + allTagsHolder[allTags[i]];

 if (sortOrder == "desc") {
 // leftovers last...
 for (var i=0;i<leftOvers.length;i++)
 markup += "*[["+leftOvers[i]+"]]\n";


config.macros.tagglyList.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
 var sortBy = params[0] ? params[0] : "title";
 var sortOrder = params[1] ? params[1] : "asc";
 var numCols = params[2] ? params[2] : 1;

 var result = store.getTaggedTiddlers(tiddler.title,sortBy);
 if (sortOrder == "desc")
 result = result.reverse();

 var listSize = result.length;
 var colSize = listSize/numCols;
 var remainder = listSize % numCols;

 var upperColsize;
 var lowerColsize;
 if (colSize != Math.floor(colSize)) {
 // it's not an exact fit so..
 lowerColsize = Math.floor(colSize);
 upperColsize = Math.floor(colSize) + 1;
 else {
 lowerColsize = colSize;
 upperColsize = colSize;

 var markup = "";
 var c=0;

 var newTaggedTable = createTiddlyElement(place,"table");
 var newTaggedBody = createTiddlyElement(newTaggedTable,"tbody");
 var newTaggedTr = createTiddlyElement(newTaggedBody,"tr");

 for (var j=0;j<numCols;j++) {
 var foo = "";
 var thisSize;

 if (j<remainder)
 thisSize = upperColsize;
 thisSize = lowerColsize;

 for (var i=0;i<thisSize;i++)
 foo += ( "*[[" + result[c++].title + "]]\n"); // was using splitList.shift() but didn't work in IE;

 var newTd = createTiddlyElement(newTaggedTr,"td",null,"tagglyTagging");



/* snip for later.....
 //var groupBy = params[3] ? params[3] : "t.title.substr(0,1)";
 //var groupBy = params[3] ? params[3] : "sortedListOfOtherTags(t,tiddler.title)";
 //var groupBy = params[3] ? params[3] : "t.modified";
 var groupBy = null; // for now. groupBy here is working but disabled for now.

 var prevGroup = "";
 var thisGroup = "";

 if (groupBy) {
 result.sort(function(a,b) {
 var t = a; var aSortVal = eval(groupBy); var aSortVal2 = eval("t".sortBy);
 var t = b; var bSortVal = eval(groupBy); var bSortVal2 = eval("t".sortBy);
 var t = b; var bSortVal2 = eval(groupBy);
 return (aSortVal == bSortVal ?
 (aSortVal2 == bSortVal2 ? 0 : (aSortVal2 < bSortVal2 ? -1 : +1)) // yuck
 : (aSortVal < bSortVal ? -1 : +1));

 if (groupBy) {
 thisGroup = eval(groupBy);
 if (thisGroup != prevGroup)
 markup += "*[["+thisGroup+']]\n';
 markup += "**[["+t.title+']]\n';
 prevGroup = thisGroup;




Use to make the sort control buttons

function getSortBy(title) {
 var tiddler = store.getTiddler(title);
 var defaultVal = config.macros.tagglyListWithSort.defaults.sortBy;
 if (!tiddler) return defaultVal;
 var usetags = config.macros.tagglyListControl.tags;
 if (tiddler.tags.contains(usetags["title"])) return "title";
 else if (tiddler.tags.contains(usetags["modified"])) return "modified";
 else if (tiddler.tags.contains(usetags["created"])) return "created";
 else return defaultVal;

function getSortOrder(title) {
 var tiddler = store.getTiddler(title);
 var defaultVal = config.macros.tagglyListWithSort.defaults.sortOrder;
 if (!tiddler) return defaultVal;
 var usetags = config.macros.tagglyListControl.tags;
 if (tiddler.tags.contains(usetags["asc"])) return "asc";
 else if (tiddler.tags.contains(usetags["desc"])) return "desc";
 else return defaultVal;

function getHideState(title) {
 var tiddler = store.getTiddler(title);
 var defaultVal = config.macros.tagglyListWithSort.defaults.hideState;
 if (!tiddler) return defaultVal;
 var usetags = config.macros.tagglyListControl.tags;
 if (tiddler.tags.contains(usetags["hide"])) return "hide";
 else if (tiddler.tags.contains(usetags["show"])) return "show";
 else return defaultVal;

function getGroupState(title) {
 var tiddler = store.getTiddler(title);
 var defaultVal = config.macros.tagglyListWithSort.defaults.groupState;
 if (!tiddler) return defaultVal;
 var usetags = config.macros.tagglyListControl.tags;
 if (tiddler.tags.contains(usetags["group"])) return "group";
 else if (tiddler.tags.contains(usetags["nogroup"])) return "nogroup";
 else return defaultVal;

function getNumCols(title) {
 var tiddler = store.getTiddler(title);
 var defaultVal = config.macros.tagglyListWithSort.defaults.numCols; // an int
 if (!tiddler) return defaultVal;
 var usetags = config.macros.tagglyListControl.tags;
 for (var i=1;i<=config.macros.tagglyListWithSort.maxCols;i++)
 if (tiddler.tags.contains(usetags["cols"+i])) return i;
 return defaultVal;

function getSortLabel(title,which) {
 // TODO. the strings here should be definable in config
 var by = getSortBy(title);
 var order = getSortOrder(title);
 var hide = getHideState(title);
 var group = getGroupState(title);
 if (which == "hide") return (hide == "show" ? "−" : "+"); // 0x25b8;
 else if (which == "group") return (group == "group" ? "normal" : "grouped");
 else if (which == "cols") return "cols±"; // &plusmn;
 else if (by == which) return which + (order == "asc" ? "↓" : "↑"); // &uarr; &darr;
 else return which;

function handleSortClick(title,which) {
 var currentSortBy = getSortBy(title);
 var currentSortOrder = getSortOrder(title);
 var currentHideState = getHideState(title);
 var currentGroupState = getGroupState(title);
 var currentNumCols = getNumCols(title);

 var tags = config.macros.tagglyListControl.tags;

 // if it doesn't exist, lets create it..
 if (!store.getTiddler(title))
 store.saveTiddler(title,title,"",config.options.txtUserName,new Date(),null);

 if (which == "hide") {
 // toggle hide state
 var newHideState = (currentHideState == "hide" ? "show" : "hide");
 if (newHideState != config.macros.tagglyListWithSort.defaults.hideState)
 else if (which == "group") {
 // toggle hide state
 var newGroupState = (currentGroupState == "group" ? "nogroup" : "group");
 if (newGroupState != config.macros.tagglyListWithSort.defaults.groupState)
 else if (which == "cols") {
 // toggle num cols
 var newNumCols = currentNumCols + 1; // confusing. currentNumCols is an int
 if (newNumCols > config.macros.tagglyListWithSort.maxCols || newNumCols > store.getTaggedTiddlers(title).length)
 newNumCols = 1;
 if (("cols"+newNumCols) != config.macros.tagglyListWithSort.defaults.groupState)
 else if (currentSortBy == which) {
 // toggle sort order
 var newSortOrder = (currentSortOrder == "asc" ? "desc" : "asc");
 if (newSortOrder != config.macros.tagglyListWithSort.defaults.sortOrder)
 else {
 // change sortBy only

 if (which != config.macros.tagglyListWithSort.defaults.sortBy)

 store.setDirty(true); // save is required now.
 story.refreshTiddler(title,false,true); // force=true

config.macros.tagglyListControl.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
 var onclick = function(e) {
 if (!e) var e = window.event;
 e.cancelBubble = true;
 if (e.stopPropagation) e.stopPropagation();
 return false;
 createTiddlyButton(place,getSortLabel(tiddler.title,params[0]),"Click to change sort options",onclick,params[0]=="hide"?"hidebutton":"button");

put it all together..
config.macros.tagglyListWithSort.handler = function (place,macroName,params,wikifier,paramString,tiddler) {
 if (tiddler && store.getTaggedTiddlers(tiddler.title).length > 0)
  // todo make this readable
 "<<tagglyListControl hide>>"+
 (getHideState(tiddler.title) != "hide" ?
 '<html><span class="tagglyLabel">'+config.macros.tagglyList.label.format([tiddler.title])+' </span></html>'+
 "<<tagglyListControl title>><<tagglyListControl modified>><<tagglyListControl created>><<tagglyListControl group>>"+(getGroupState(tiddler.title)=="group"?"":"<<tagglyListControl cols>>")+"\n" +
 "<<tagglyList" + (getGroupState(tiddler.title)=="group"?"ByTag ":" ") + getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+" "+getNumCols(tiddler.title)+">>" // hacky
 // + \n----\n" +
 //"<<tagglyList "+getSortBy(tiddler.title)+" "+getSortOrder(tiddler.title)+">>"
 : ""),

config.macros.tagglyTagging = { handler: config.macros.tagglyListWithSort.handler };


So we don't see the sort tags.
(note, they are still there when you edit. Will that be too annoying?

// based on tags.handler
config.macros.hideSomeTags.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
 var theList = createTiddlyElement(place,"ul");
 if(params[0] && store.tiddlerExists[params[0]])
 tiddler = store.getTiddler(params[0]);
 var lingo = config.views.wikified.tag;
 var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;
 for(var t=0; t<tiddler.tags.length; t++)
 if (!this.tagsToHide.contains(tiddler.tags[t])) // this is the only difference from tags.handler...



!Refresh everything when we save a tiddler. So the tagged lists never get stale. Is this too slow???

function refreshAllVisible() {
 story.forEachTiddler(function(title,element) {
   if (element.getAttribute("dirty") != "true")

story.saveTiddler_orig_mptw = story.saveTiddler;
story.saveTiddler = function(title,minorUpdate) {
 var result = this.saveTiddler_orig_mptw(title,minorUpdate);
// refreshAllVisible();
 return result;

store.removeTiddler_orig_mptw = store.removeTiddler;
store.removeTiddler = function(title) {
// refreshAllVisible();

config.shadowTiddlers.TagglyTaggingStyles = "/***\nTo use, add {{{[[TagglyTaggingStyles]]}}} to your StyleSheet tiddler, or you can just paste the CSS in directly. See also ViewTemplate, EditTemplate and TagglyTagging.\n***/\n/*{{{*/\n.tagglyTagged li.listTitle { display:none;}\n.tagglyTagged li { display: inline; font-size:90%; }\n.tagglyTagged ul { margin:0px; padding:0px; }\n.tagglyTagging { padding-top:0.5em; }\n.tagglyTagging li.listTitle { display:none;}\n.tagglyTagging ul { margin-top:0px; padding-top:0.5em; padding-left:2em; margin-bottom:0px; padding-bottom:0px; }\n\n/* .tagglyTagging .tghide { display:inline; } */\n\n.tagglyTagging { vertical-align: top; margin:0px; padding:0px; }\n.tagglyTagging table { margin:0px; padding:0px; }\n\n\n.tagglyTagging .button { display:none; margin-left:3px; margin-right:3px; }\n.tagglyTagging .button, .tagglyTagging .hidebutton { color:#aaa; font-size:90%; border:0px; padding-left:0.3em;padding-right:0.3em;}\n.tagglyTagging .button:hover, .hidebutton:hover { background:#eee; color:#888; }\n.selected .tagglyTagging .button { display:inline; }\n\n.tagglyTagging .hidebutton { color:white; } /* has to be there so it takes up space. tweak if you're not using a white tiddler bg */\n.selected .tagglyTagging .hidebutton { color:#aaa }\n\n.tagglyLabel { color:#aaa; font-size:90%; }\n\n.tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }\n.tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}\n.tagglyTagging ul ul li {margin-left:0.5em; }\n\n.editLabel { font-size:90%; padding-top:0.5em; }\n/*}}}*/\n";



// // <html>&#x25b8;&#x25be;&minus;&plusmn;</html>
Type the text for 'TagglyTagging'
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 6100 $)|
|Date:|$Date: 2008-07-27 01:42:07 +1000 (Sun, 27 Jul 2008) $|
|Author:|Simon Baird <>|


	parseTagExpr: function(debug) {

		if (this.trim() == "")
			return "(true)";

		var anyLogicOp = /(!|&&|\|\||\(|\))/g;
		var singleLogicOp = /^(!|&&|\|\||\(|\))$/;

		var spaced = this.
			// because square brackets in templates are no good
			// this means you can use [(With Spaces)] instead of [[With Spaces]]
			replace(/\[\(/g," [[").
			replace(/\)\]/g,"]] ").
			// space things out so we can use readBracketedList. tricky eh?
			replace(anyLogicOp," $1 ");

		var expr = "";

		var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!

		for (var i=0;i<tokens.length;i++)
			if (tokens[i].match(singleLogicOp))
				expr += tokens[i];
				expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think

		if (debug)

		return '('+expr+')';


	getTiddlersByTagExpr: function(tagExpr,sortField) {

		var result = [];

		var expr = tagExpr.parseTagExpr();

		store.forEachTiddler(function(title,tiddler) {
			if (eval(expr))

			sortField = "title";

		result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});

		return result;

config.taggly = {

	// for translations
	lingo: {
		labels: {
			asc:        "\u2191", // down arrow
			desc:       "\u2193", // up arrow
			title:      "title",
			modified:   "modified",
			created:    "created",
			show:       "+",
			hide:       "-",
			normal:     "normal",
			group:      "group",
			commas:     "commas",
			sitemap:    "sitemap",
			numCols:    "cols\u00b1", // plus minus sign
			label:      "Tagged as '%0':",
			exprLabel:  "Matching tag expression '%0':",
			excerpts:   "excerpts",
			descr:      "descr",
			slices:     "slices",
			contents:   "contents",
			sliders:    "sliders",
			noexcerpts: "title only",
			noneFound:  "(none)"

		tooltips: {
			title:      "Click to sort by title",
			modified:   "Click to sort by modified date",
			created:    "Click to sort by created date",
			show:       "Click to show tagging list",
			hide:       "Click to hide tagging list",
			normal:     "Click to show a normal ungrouped list",
			group:      "Click to show list grouped by tag",
			sitemap:    "Click to show a sitemap style list",
			commas:     "Click to show a comma separated list",
			numCols:    "Click to change number of columns",
			excerpts:   "Click to show excerpts",
			descr:      "Click to show the description slice",
			slices:     "Click to show all slices",
			contents:   "Click to show entire tiddler contents",
			sliders:    "Click to show tiddler contents in sliders",
			noexcerpts: "Click to show entire title only"

		tooDeepMessage: "* //sitemap too deep...//"

	config: {
		showTaggingCounts: true,
		listOpts: {
			// the first one will be the default
			sortBy:     ["title","modified","created"],
			sortOrder:  ["asc","desc"],
			hideState:  ["show","hide"],
			listMode:   ["normal","group","sitemap","commas"],
			numCols:    ["1","2","3","4","5","6"],
			excerpts:   ["noexcerpts","excerpts","descr","slices","contents","sliders"]
		valuePrefix: "taggly.",
		excludeTags: ["excludeLists","excludeTagging"],
		excerptSize: 50,
		excerptMarker: "/%"+"%/",
		siteMapDepthLimit: 25

	getTagglyOpt: function(title,opt) {
		var val = store.getValue(title,this.config.valuePrefix+opt);
		return val ? val : this.config.listOpts[opt][0];

	setTagglyOpt: function(title,opt,value) {
		if (!store.tiddlerExists(title))
			// create it silently
			store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");
		// if value is default then remove it to save space
		return store.setValue(title,
			value == this.config.listOpts[opt][0] ? null : value);

	getNextValue: function(title,opt) {
		var current = this.getTagglyOpt(title,opt);
		var pos = this.config.listOpts[opt].indexOf(current);
		// a little usability enhancement. actually it doesn't work right for grouped or sitemap
		var limit = (opt == "numCols" ? store.getTiddlersByTagExpr(title).length : this.config.listOpts[opt].length);
		var newPos = (pos + 1) % limit;
		return this.config.listOpts[opt][newPos];

	toggleTagglyOpt: function(title,opt) {
		var newVal = this.getNextValue(title,opt);

	createListControl: function(place,title,type) {
		var lingo = config.taggly.lingo;
		var label;
		var tooltip;
		var onclick;

		if ((type == "title" || type == "modified" || type == "created")) {
			// "special" controls. a little tricky. derived from sortOrder and sortBy
			label = lingo.labels[type];
			tooltip = lingo.tooltips[type];

			if (this.getTagglyOpt(title,"sortBy") == type) {
				label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
				onclick = function() {
					return false;
			else {
				onclick = function() {
					return false;
		else {
			// "regular" controls, nice and simple
			label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
			tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
			onclick = function() {
				return false;

		// hide button because commas don't have columns
		if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
			createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");

	makeColumns: function(orig,numCols) {
		var listSize = orig.length;
		var colSize = listSize/numCols;
		var remainder = listSize % numCols;

		var upperColsize = colSize;
		var lowerColsize = colSize;

		if (colSize != Math.floor(colSize)) {
			// it's not an exact fit so..
			upperColsize = Math.floor(colSize) + 1;
			lowerColsize = Math.floor(colSize);

		var output = [];
		var c = 0;
		for (var j=0;j<numCols;j++) {
			var singleCol = [];
			var thisSize = j < remainder ? upperColsize : lowerColsize;
			for (var i=0;i<thisSize;i++)

		return output;

	drawTable: function(place,columns,theClass) {
		var newTable = createTiddlyElement(place,"table",null,theClass);
		var newTbody = createTiddlyElement(newTable,"tbody");
		var newTr = createTiddlyElement(newTbody,"tr");
		for (var j=0;j<columns.length;j++) {
			var colOutput = "";
			for (var i=0;i<columns[j].length;i++)
				colOutput += columns[j][i];
			var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
		return newTable;

	createTagglyList: function(place,title,isTagExpr) {
		switch(this.getTagglyOpt(title,"listMode")) {
			case "group":  return this.createTagglyListGrouped(place,title,isTagExpr); break;
			case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
			case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
			case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;

	getTaggingCount: function(title,isTagExpr) {
		// thanks to Doug Edmunds
		if (this.config.showTaggingCounts) {
			var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
			if (tagCount > 0)
				return " ("+tagCount+")";
		return "";

	getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
		return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);

	getExcerpt: function(inTiddlerTitle,title,indent) {
		if (!indent)
			indent = 1;

		var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
		var t = store.getTiddler(title);

		if (t && displayMode == "excerpts") {
			var text = t.text.replace(/\n/," ");
			var marker = text.indexOf(this.config.excerptMarker);
			if (marker != -1) {
				return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
			else if (text.length < this.config.excerptSize) {
				return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
			else {
				return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
		else if (t && displayMode == "contents") {
			return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
		else if (t && displayMode == "sliders") {
			return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
		else if (t && displayMode == "descr") {
			var descr = store.getTiddlerSlice(title,'Description');
			return descr ? " {{excerpt{" + descr  + "}}}" : "";
		else if (t && displayMode == "slices") {
			var result = "";
			var slices = store.calcAllSlices(title);
			for (var s in slices)
				result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
			return result ? "\n{{excerpt excerptIndent{\n" + result  + "}}}" : "";
		return "";

	notHidden: function(t,inTiddler) {
		if (typeof t == "string")
			t = store.getTiddler(t);
		return (!t || !t.tags.containsAny(this.config.excludeTags) ||
				(inTiddler && this.config.excludeTags.contains(inTiddler)));

	// this is for normal and commas mode
	createTagglyListNormal: function(place,title,useCommas,isTagExpr) {

		var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);

		if (this.getTagglyOpt(title,"sortOrder") == "desc")
			list = list.reverse();

		var output = [];
		var first = true;
		for (var i=0;i<list.length;i++) {
			if (this.notHidden(list[i],title)) {
				var countString = this.getTaggingCount(list[i].title);
				var excerpt = this.getExcerpt(title,list[i].title);
				if (useCommas)
					output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
					output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");

				first = false;

		return this.drawTable(place,
			this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
			useCommas ? "commas" : "normal");

	// this is for the "grouped" mode
	createTagglyListGrouped: function(place,title,isTagExpr) {
		var sortBy = this.getTagglyOpt(title,"sortBy");
		var sortOrder = this.getTagglyOpt(title,"sortOrder");

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")
			list = list.reverse();

		var leftOvers = []
		for (var i=0;i<list.length;i++)

		var allTagsHolder = {};
		for (var i=0;i<list.length;i++) {
			for (var j=0;j<list[i].tags.length;j++) {

				if (list[i].tags[j] != title) { // not this tiddler

					if (this.notHidden(list[i].tags[j],title)) {

						if (!allTagsHolder[list[i].tags[j]])
							allTagsHolder[list[i].tags[j]] = "";

						if (this.notHidden(list[i],title)) {
							allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
										+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";

							leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers


		var allTags = [];
		for (var t in allTagsHolder)

		var sortHelper = function(a,b) {
			if (a == b) return 0;
			if (a < b) return -1;
			return 1;

		allTags.sort(function(a,b) {
			var tidA = store.getTiddler(a);
			var tidB = store.getTiddler(b);
			if (sortBy == "title") return sortHelper(a,b);
			else if (!tidA && !tidB) return 0;
			else if (!tidA) return -1;
			else if (!tidB) return +1;
			else return sortHelper(tidA[sortBy],tidB[sortBy]);

		var leftOverOutput = "";
		for (var i=0;i<leftOvers.length;i++)
			if (this.notHidden(leftOvers[i],title))
				leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";

		var output = [];

		if (sortOrder == "desc")
		else if (leftOverOutput != "")
			// leftovers first...

		for (var i=0;i<allTags.length;i++)
			if (allTagsHolder[allTags[i]] != "")
				output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);

		if (sortOrder == "desc" && leftOverOutput != "")
			// leftovers last...

		return this.drawTable(place,


	// used to build site map
	treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")

		var indent = "";
		for (var j=0;j<depth;j++)
			indent += "*"

		var childOutput = "";

		if (depth > this.config.siteMapDepthLimit)
			childOutput += indent + this.lingo.tooDeepMessage;
			for (var i=0;i<list.length;i++)
				if (list[i].title != title)
					if (this.notHidden(list[i].title,this.config.inTiddler))
						childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);

		if (depth == 0)
			return childOutput;
			return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;

	// this if for the site map mode
	createTagglyListSiteMap: function(place,title,isTagExpr) {
		this.config.inTiddler = title; // nasty. should pass it in to traverse probably
		var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
		return this.drawTable(place,
				this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic

	macros: {
		tagglyTagging: {
			handler: function (place,macroName,params,wikifier,paramString,tiddler) {
				var parsedParams = paramString.parseParams("tag",null,true);
				var refreshContainer = createTiddlyElement(place,"div");

				// do some refresh magic to make it keep the list fresh - thanks Saq

				var tag = getParam(parsedParams,"tag");
				var expr = getParam(parsedParams,"expr");

				if (expr) {
				else {
					if (tag) {
					else {

			refresh: function(place) {
				var title = place.getAttribute("title");
				var isTagExpr = place.getAttribute("isTagExpr") == "true";
				var showEmpty = place.getAttribute("showEmpty") == "true";
				var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
				if (countFound > 0 || showEmpty) {
					var lingo = config.taggly.lingo;
					if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
								isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
						if (countFound == 0 && showEmpty)

	// todo fix these up a bit
	styles: [
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
"	margin-top:0px; padding-top:0.5em; padding-left:2em;",
"	margin-bottom:0px; padding-bottom:0px;",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
"	color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
"	border:0px; padding-left:0.3em;padding-right:0.3em;",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active  {",
"	border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
"  margin-bottom:0.5em; }",
".tagglyTagging .indent1  { margin-left:3em;  }",
".tagglyTagging .indent2  { margin-left:4em;  }",
".tagglyTagging .indent3  { margin-left:5em;  }",
".tagglyTagging .indent4  { margin-left:6em;  }",
".tagglyTagging .indent5  { margin-left:7em;  }",
".tagglyTagging .indent6  { margin-left:8em;  }",
".tagglyTagging .indent7  { margin-left:9em;  }",
".tagglyTagging .indent8  { margin-left:10em; }",
".tagglyTagging .indent9  { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",

	init: function() {
		config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;



By Saq Imtiaz

// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed

config.formatters.unshift( {
	name: "inlinesliders",
	// match: "\\+\\+\\+\\+|\\<slider",
	match: "\\<slider",
	// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
	lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
	handler: function(w) {
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
			var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
			var panel = createTiddlyElement(w.output,"div",null,"sliderPanel"); = (lookaheadMatch[1] == '+' ? "block" : "none");
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
   onClickSlider : function(e) {
		if(!e) var e = window.event;
		var n = this.nextSibling; = ("none") ? "block" : "none";
		return false;


/* created by TagglyTaggingPlugin */
.tagglyTagging { padding-top:0.5em; }
.tagglyTagging li.listTitle { display:none; }
.tagglyTagging ul {
	margin-top:0px; padding-top:0.5em; padding-left:2em;
	margin-bottom:0px; padding-bottom:0px;
.tagglyTagging { vertical-align: top; margin:0px; padding:0px; }
.tagglyTagging table { margin:0px; padding:0px; }
.tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }
.tagglyTagging .button, .tagglyTagging .hidebutton {
	color:[[ColorPalette::TertiaryLight]]; font-size:90%;
	border:0px; padding-left:0.3em;padding-right:0.3em;
.tagglyTagging .button:hover, .hidebutton:hover,
.tagglyTagging .button:active, .hidebutton:active  {
	border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];
.selected .tagglyTagging .button { visibility:visible; }
.tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }
.selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }
.tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }
.tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }
.tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}
.tagglyTagging ul ul li {margin-left:0.5em; }
.editLabel { font-size:90%; padding-top:0.5em; }
.tagglyTagging .commas { padding-left:1.8em; }
/* not technically tagglytagging but will put them here anyway */
.tagglyTagged li.listTitle { display:none; }
.tagglyTagged li { display: inline; font-size:90%; }
.tagglyTagged ul { margin:0px; padding:0px; }
.excerpt { color:[[ColorPalette::TertiaryDark]]; }
.excerptIndent { margin-left:4em; }
div.tagglyTagging table,
div.tagglyTagging table tr,
 {border-style:none!important; }
.tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;
  margin-bottom:0.5em; }
.tagglyTagging .indent1  { margin-left:3em;  }
.tagglyTagging .indent2  { margin-left:4em;  }
.tagglyTagging .indent3  { margin-left:5em;  }
.tagglyTagging .indent4  { margin-left:6em;  }
.tagglyTagging .indent5  { margin-left:7em;  }
.tagglyTagging .indent6  { margin-left:8em;  }
.tagglyTagging .indent7  { margin-left:9em;  }
.tagglyTagging .indent8  { margin-left:10em; }
.tagglyTagging .indent9  { margin-left:11em; }
.tagglyTagging .indent10 { margin-left:12em; }
.tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }

|Created by|SaqImtiaz|
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.

<<toggleSideBar "Toggle Sidebar">>

{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)

You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}

*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour.
*20-07-06: version 0.11
*27-04-06: version 0.1: working.


         styleHide :  "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
         styleShow : " ",
         arrow1: "«",
         arrow2: "»"

config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
          var tooltip= params[1]||'toggle sidebar';
          var mode = (params[2] && params[2]=="hide")? "hide":"show";
          var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
          var label= (params[0]&&params[0]!='.')?params[0]+" "+arrow:arrow;
          var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
          if (mode == "hide")

config.macros.toggleSideBar.onToggleSideBar = function(){
          var sidebar = document.getElementById("sidebar");
          var settings = config.macros.toggleSideBar.settings;
          if (sidebar.getAttribute("toggle")=='hide')

     return false;

setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");

|~ViewToolbar|closeTiddler closeOthers editTiddler > fields syncing permalink references jump|
|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|

<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'><span class="miniTag" macro="miniTag"></span></div>
<div class='subtitle'>Updated <span macro='view modified date [[MMM DD, YYYY]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[MMM DD, YYYY]]'></span>)<BR><BR></div>
<div class='viewer' macro='view text wikified'></div>
<div class="tagglyTagging" macro="tagglyTagging"><BR><BR></div>
<div class="tagglyTagged" macro="hideSomeTags"></div>
<div class='tagClear'></div>
!!IP Addresses:
# test - Testing
# www - Web Server
# auth - Authentication & DNS
# files - Storage
# mail - Email
# Final Exam

Like most wikis, TiddlyWiki supports a range of simplified character formatting:
| !To get | !Type this |h
| ''Bold'' | {{{''Bold''}}} |
| ==Strikethrough== | {{{==Strikethrough==}}} |
| __Underline__ | {{{__Underline__}}} (that's two underline characters) |
| //Italic// | {{{//Italic//}}} |
| Superscript: 2^^3^^=8 | {{{2^^3^^=8}}} |
| Subscript: a~~ij~~ = -a~~ji~~ | {{{a~~ij~~ = -a~~ji~~}}} |
| @@highlight@@ | {{{@@highlight@@}}} |
| Tiddler Comments | {{{/%}}} text {{{%/}}}. |
| [[Make me a tiddler]] | {{{[[Make me a tiddler]]}}} |
| ~NoTiddler | {{{~NoTiddler}}} |
| {{{This is monotype}}} | {{{{{{This is monotype}}}}}} |

|>| colspan |
| rowspan |left|
|~| right|
|bgcolor(#a0ffa0):colored| center |
For advanced effects, you can control the CSS style of a table by adding a row like this:

The highlight can also accept CSS syntax to directly style the text:
@@color:green;green coloured@@
@@background-color:#ff0000;color:#ffffff;red coloured@@
@@text-shadow:black 3px 3px 8px;font-size:18pt;display:block;margin:1em 1em 1em 1em;border:1px solid black;Access any CSS style@@
!!@@display:block;text-align:center;centered text@@

//For backwards compatibility, the following highlight syntax is also accepted://
@@bgcolor(#ff0000):color(#ffffff):red coloured@@
@@bgcolor(#ff0000):color(#ffffff):red coloured@@


@@color(yourcolorhere):colored text@@
@@color(fuchsia):colored text@@
@@bgcolor(yourcolorhere):your text here@@

[[Existing Tiddler Name|UglyTiddlerName]]

<hr> = ----

*Entry One
**Sub-entry A
***Sub-sub-entry i
***Sub-sub-entry ii
**Sub-entry B
*Entry Two
*Entry Three
Use number signs (#'s) instead of asterisks for <OL type=1>

|!Headings: add an exclamation point (!) right after the vertical bar.|!Heading2|!Heading3|
|Row 1, Column 1|Row 1, Column 2|Row 1, Column 3|
|>|>|Have one row span multiple columns by using a >|
|Have one column span multiple rows by using a ~|>| Use a space to right-align text in a cell|
|~|>| Enclose text in a cell with spaces to center it |
|>|>|bgcolor(green):Add color to a cell using bgcolor(yourcolorhere):|
|Add a caption by ending the table with a vertical bar followed by a c|c

!Header 1
!!Header 2
!!!Header 3
!!!!Header 4
!!!!!Header 5

Here's the code for a blockquote:
Here's the quoted text.


[[Calendar generator|]]

Entities in HTML documents allow characters to be entered that can't easily be typed on an ordinary keyboard. They take the form of an ampersand (&), an identifying string, and a terminating semi-colon (;). There's a complete reference [[here|]]; some of the more common and useful ones are shown below. Also see [[Paul's Notepad|]] for a more complete list.

|>|>|>|>|>|>| !HTML Entities |
| &amp;nbsp; | &nbsp; | no-break space | &nbsp;&nbsp; | &amp;apos; | &apos; | single quote, apostrophe |
| &amp;ndash; | &ndash; | en dash |~| &amp;quot; | &quot; | quotation mark |
| &amp;mdash; | &mdash; | em dash |~| &amp;prime; | &prime; | prime; minutes; feet |
| &amp;hellip; | &hellip; |	horizontal ellipsis |~| &amp;Prime; | &Prime; | double prime; seconds; inches |
| &amp;copy; | &copy; | Copyright symbol |~| &amp;lsquo; | &lsquo; | left single quote |
| &amp;reg; | &reg; | Registered symbol |~| &amp;rsquo; | &rsquo; | right  single quote |
| &amp;trade; | &trade; | Trademark symbol |~| &amp;ldquo; | &ldquo; | left double quote |
| &amp;dagger; | &dagger; | dagger |~| &amp;rdquo; | &rdquo; | right double quote |
| &amp;Dagger; | &Dagger; | double dagger |~| &amp;laquo; | &laquo; | left angle quote |
| &amp;para; | &para; | paragraph sign |~| &amp;raquo; | &raquo; | right angle quote |
| &amp;sect; | &sect; | section sign |~| &amp;times; | &times; | multiplication symbol |
| &amp;uarr; | &uarr; | up arrow |~| &amp;darr; | &darr; | down arrow |
| &amp;larr; | &larr; | left arrow |~| &amp;rarr; | &rarr; | right arrow |
| &amp;lArr; | &lArr; | double left arrow |~| &amp;rArr; | &rArr; | double right arrow |
| &amp;harr; | &harr; | left right arrow |~| &amp;hArr; | &hArr; | double left right arrow |

The table below shows how accented characters can be built up by subsituting a base character into the various accent entities in place of the underscore ('_'):

|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>|>| !Accented Characters |
| grave accent | &amp;_grave; | &Agrave; | &agrave; | &Egrave; | &egrave; | &Igrave; | &igrave; | &Ograve; | &ograve; | &Ugrave; | &ugrave; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
| acute accent | &amp;_acute; | &Aacute; | &aacute; | &Eacute; | &eacute; | &Iacute; | &iacute; | &Oacute; | &oacute; | &Uacute; | &uacute; | &nbsp; | &nbsp; | &Yacute; | &yacute; | &nbsp; | &nbsp; |
| circumflex accent | &amp;_circ; | &Acirc; | &acirc; | &Ecirc; | &ecirc; | &Icirc; | &icirc; | &Ocirc; | &ocirc; | &Ucirc; | &ucirc; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
| umlaut mark | &amp;_uml; | &Auml; | &auml; |  &Euml; | &euml; | &Iuml; | &iuml; | &Ouml; | &ouml; | &Uuml; | &uuml; | &nbsp; | &nbsp; | &Yuml; | &yuml; | &nbsp; | &nbsp; |
| tilde | &amp;_tilde; | &Atilde; | &atilde; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &Otilde; | &otilde; | &nbsp; | &nbsp; | &Ntilde; | &ntilde; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
| ring | &amp;_ring; | &Aring; | &aring; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
| slash | &amp;_slash; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &Oslash; | &oslash; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |
| cedilla | &amp;_cedil; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &Ccedil; | &ccedil; |

<HTML><a href="">CSS Info</a></html>

Type the text for 'excludeLists'
Type the text for 'excludeSearch'
config.macros.listTags = { text: "Hello" };
config.macros.listTags.handler = function(place,macroName,params)
	var tagged = store.getTaggedTiddlers(params[0],params[1]);
//<< Second parameter is field to sort by (eg, title, modified, modifier or text)
	var ul = createTiddlyElement(place,"ul",null,null,"");
	for(var r=0;r<tagged.length;r++)
		var li = createTiddlyElement(ul,"li",null,null,"");
|''Name:''|Plugin setDefaults|
|''Version:''|1.0.1 (2006-03-16)|
|''Author:''|Jim Barr (jim [at] barr [dot] net)|
|''Licence:''|[[BSD open source license]]|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|

These settings simply set "default" values for several system features and Plugins.

Standard settings:
config.options.chkRegExpSearch         = false;         // default false
config.options.chkCaseSensitiveSearch  = false;         // default false
config.options.chkAnimate              = false;          // default true
//config.options.txtUserName             = "Nick";    // default "YourName"
config.options.chkSaveBackups          = false;          // default true
config.options.chkAutoSave             = false;          // default false
config.options.chkGenerateAnRssFeed    = false;         // default false
config.options.chkSaveEmptyTemplate    = false;         // default false
config.options.chkOpenInNewWindow      = true;          // default true
config.options.chkToggleLinks          = false;         // default false
config.options.chkHttpReadOnly         = true;         // default true
config.options.chkForceMinorUpdate     = false;         // default false
config.options.chkConfirmDelete        = true;          // default true
config.options.txtBackupFolder         = "";            // default ""
config.options.txtMainTab              = "tabTimeline"; // default "tabTimeline"
config.options.txtMoreTab              = "moreTabAll";  // default "moreTabAll"
config.options.txtMaxEditRows          = "30";          // default "30"
config.options.chkInsertTabs = true;    		// tab inserts a tab when editing a tiddler


Custom Plugin settings:
config.options.chkSinglePageMode       = false;          // default "true"
config.options.chkSearchTitlesFirst       = true;
config.options.chkSearchList           = true;           // default "false"
config.messages.messageClose.text      = "X";           // default "close"
// config.views.wikified.defaultText      = "";            // default "The tiddler '%0' doesn't yet exist. Double-click to create it"
config.options.chkStepWiseNavigationOn = true;           // default "false"
config.options.chkDisableAutoSelect       =true;
config.options.chkTextAreaExtensions    =true;
Type the text for 'systemConfig'
Type the text for 'systemTiddler'