Skip to content

Commit

Permalink
feat: add chap and pap methods of authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
LwveMike committed Apr 16, 2024
1 parent 224b34f commit 97e4f0f
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 300 deletions.
178 changes: 15 additions & 163 deletions packages/playground/server/tac_plus.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,172 +5,24 @@ default authentication = file /etc/passwd
accounting syslog;
accounting file = /var/log/tac_plus/tac_plus.acct

# ACL for network_admin group

acl = network_admin {
# allow access from all sources
permit = .*
# implicit deny (ie: anything else)
}

# ACL for sys_admin group

acl = sys_admin {
# allow access from 10.10.10.250 only
permit = .*
# permit = ^10\.10\.10\.2$
# implicit deny (ie: anything else)
}

# network_admin group, full access to network devices

group = network_admin {
default service = permit
acl = network_admin
service = exec {
priv-lvl = 15
}
}
# sys_admin group, only has read access to the network devices and can change the access vlan on an interface

group = sys_admin {
default service = deny
expires = "Jan 1 2015"
acl = sys_admin
service = exec {
priv-lvl = 15
}
cmd = enable {
permit .*
}
cmd = show {
permit .*
}
cmd = exit {
permit .*
}
cmd = configure {
permit .*
}
cmd = interface {
permit Ethernet.*
permit FastEthernet.*
permit GigabitEthernet.*
}
cmd = switchport {
permit "access vlan.*"
permit "trunk encapsulation.*"
permit "mode.*"
permit "trunk allowed vlan.*"
}
cmd = description {
permit .*
}
}

#user1
user = user1 {
default service = permit
pap = cleartext user1
service = exec {
priv-lvl = 15
security-role = security-admin
}
}

#user2
user = user2 {
pap = cleartext user2
service = exec {
priv-lvl = 15
}
}

user = user_tac1 {
default service = permit
pap = cleartext tac
service = exec {
priv-lvl = 15
security-role = security-admin
}
}
#user2
user = user_tac2 {
pap = cleartext tac
service = exec {
priv-lvl = 15
}
}

user = user_command {
pap = cleartext com
service = exec {
priv-lvl = 15
}
user = test_chap {
chap = cleartext test_chap_password

service = management {
priv-lvl=15
role="admin"
}
}

user = test_login {
login = cleartext test_login_password

#user3
user = user3 {
chap = cleartext user3
service = exec {
priv-lvl = 15
}
service = idk {
priv-lvl=10
role="user"
}
}

#user4
user = user4 {
chap = cleartext user4
}

# User jonathanm using DES password and enable passwords

user = jonathanm {
member = network_admin
login = des 6/1aYAL9zcCe.
enable = des dBFJQefS4S4Jw
}

# User bob authenticating from the system /etc/passwd and the default enable password

user = bob {
login = file /etc/passwd
member = sys_admin
service = exec {
priv-lvl = 11
}
}

user = root {
member = network_admin
}

user = netop {
login = file /etc/passwd
member = network_admin
}

user = admin {
pap = cleartext admin
member = network_admin
}

user = sorin {
login = cleartext topcik

service = nfa {
role = manager
car = audi
}
}

user = cristi {
login = cleartext f30

service = nfa {
role = pussykiller
car = bmw
chubby = yes
}
user = test_pap {
pap = cleartext test_pap_password
}

86 changes: 47 additions & 39 deletions packages/playground/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Client, Header, PRIVILEGE_LEVELS } from '@noction/tacacs-plus'
import type { AuthenType } from '@noction/tacacs-plus'
import { AUTHEN_TYPES, Client, PRIVILEGE_LEVELS } from '@noction/tacacs-plus'

const client = new Client({
host: '127.0.0.1',
port: 49,
// secret: 'testing123',
majorVersion: Header.MAJOR_VERSIONS.TAC_PLUS_MAJOR_VER,
minorVersion: Header.MINOR_VERSIONS.TAC_PLUS_MINOR_VER_DEFAULT,
// secret: 'tac_test',
logger: {
// TODO(lwvemike): remove before release
/* eslint-disable-next-line no-console */
Expand All @@ -18,43 +17,52 @@ const client = new Client({
},
})

const FUNCTION = 'authentication' as 'authentication' | 'authorization'
const SERVICES = ['management', 'idk']
const CREDENTIALS = {
username: 'test_pap',
password: 'test_pap_password',
} as const
const SELECTED_AUTHEN_TYPE: AuthenType = AUTHEN_TYPES.TAC_PLUS_AUTHEN_TYPE_PAP

;(async () => {
const CREDENTIALS: Record<'username' | 'password', string> = {
username: 'cristi',
password: 'f30',
if (FUNCTION === 'authentication') {
return await authenticatinon()
}

const SERVICE = 'authorization' as 'authorization' | 'authentication'

if (SERVICE === 'authentication') {
try {
const res = await client.authenticateASCII({
username: CREDENTIALS.username,
password: CREDENTIALS.password,
privLvl: PRIVILEGE_LEVELS.TAC_PLUS_PRIV_LVL_ROOT,
})

// eslint-disable-next-line no-console
console.log(res)
}
catch (err) {
// eslint-disable-next-line no-console
console.log(err)
}
return await authorization()
})()

async function authorization() {
try {
const res = await client.authorize({
username: CREDENTIALS.username,
services: SERVICES,
})

// eslint-disable-next-line no-console
console.log(res)
}
else if (SERVICE === 'authorization') {
try {
const res = await client.authorize({
username: CREDENTIALS.username,
services: ['nfa'],
})

// eslint-disable-next-line no-console
console.log(res)
}
catch (err) {
// eslint-disable-next-line no-console
console.log(err)
}
catch (err) {
// eslint-disable-next-line no-console
console.log(err)
}
})()
}

async function authenticatinon() {
try {
const res = await client.authenticate({
username: CREDENTIALS.username,
password: CREDENTIALS.password,
privLvl: PRIVILEGE_LEVELS.TAC_PLUS_PRIV_LVL_ROOT,
authenType: SELECTED_AUTHEN_TYPE,
})

// eslint-disable-next-line no-console
console.log(res)
}
catch (err) {
// eslint-disable-next-line no-console
console.log(err)
}
}
10 changes: 10 additions & 0 deletions packages/tacacs-plus/src/authentication/login/ascii.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Buffer } from 'node:buffer'
import { Header } from '../../header'
import type { CreateAuthenticationDataReturn } from '../../types'

export function createAsciiAuthenticationData(): CreateAuthenticationDataReturn {
return {
data: Buffer.alloc(0),
minorVersion: Header.MINOR_VERSIONS.TAC_PLUS_MINOR_VER_DEFAULT,
}
}
26 changes: 26 additions & 0 deletions packages/tacacs-plus/src/authentication/login/chap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Buffer } from 'node:buffer'
import { createHash, randomBytes } from 'node:crypto'
import type { CreateAuthenticationDataReturn } from '../../types'
import { Header } from '../../header'

export function createChapAuthenticationData(password: string): CreateAuthenticationDataReturn {
const pppId = randomBytes(1)
const challenge = randomBytes(49)

const data = Buffer.concat([
pppId,
challenge,
createHash('md5').update(
Buffer.concat([
pppId,
Buffer.from(password),
challenge,
]),
).digest(),
])

return {
data,
minorVersion: Header.MINOR_VERSIONS.TAC_PLUS_MINOR_VER_ONE,
}
}
14 changes: 14 additions & 0 deletions packages/tacacs-plus/src/authentication/login/pap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Buffer } from 'node:buffer'
import { Header } from '../../header'
import type { CreateAuthenticationDataReturn } from '../../types'

/**
* @deprecated
* @description In Tacacs+ RFC this is obsolete because of security implications
*/
export function createPapAuthenticationData(password: string): CreateAuthenticationDataReturn {
return {
minorVersion: Header.MINOR_VERSIONS.TAC_PLUS_MINOR_VER_ONE,
data: Buffer.from(password, 'ascii'),
}
}
Loading

0 comments on commit 97e4f0f

Please sign in to comment.