From: Don Pich on
I'm trying to compose a tcl script to read a username for our radius
server, and modify if it matches a couple of conditions.

First off, here is a typical username that I would want to modify:
0900000023000003780a2202fc0000229f

This is a hex string returned from a dslam. The issue is that the last 8
characters of the string can change on a whim. So I can't use it for
authentication data. So I'll need to hack them off. Character's 19
through 26 contain the IP address of the device. So 0a2202fc equals the
IP address 10.34.2.252. I will have a list of all the devices I will
need to compare against.

So here is my plan:

1) Read the username
2) If the length of the username equals 34, send it into an if/else
a) Read characters 19~26
b) Comapre them to a(n) external file/array that has 300+ objects -
Need help here
c) If the value retrieved from 19~26 matches a 8 digit hex string
stored in array/external file, truncate the last 8 characters of the
username and store it as NEW_username.
i.e. 0900000023000003780a2202fc0000229f will be modified to
0900000023000003780a2202fc
3) ELSE - do nothing and send the username through as presented.

With my elementary knowledge of tcl, I got a start with this.

proc ProcessBASIP {request response environ} {
set username [ $request get User-Name ]

if { [ string length $username ] == 34} {
string equal
string trimright
# SETUP NEW USERNAME
$environ put User-Name $NEW_username
}
else {
$environ put User-Name $username
}

That's as far as I have gotten. I understand some computer languages,
but regular expressions and tcl are a bit above me.

Any help you can give me would be appreciated.

Thanks,
Don
From: Richard Owlett on
The OP states at end of post that he is a newbie, so being a
relative newbie myself, I'm perhaps going to be more verbose than
most.[especially my variable names and comments ;]


Don Pich wrote:
> I'm trying to compose a tcl script to read a username for our radius
> server, and modify if it matches a couple of conditions.
>
> First off, here is a typical username that I would want to modify:
> 0900000023000003780a2202fc0000229f
0123456789012345678901234567890123
111111111122222222223333
Note that Tcl uses 0 {not 1} as index of list/array/vector/...


>
> This is a hex string returned from a dslam. The issue is that the last 8
> characters of the string can change on a whim. So I can't use it for
> authentication data. So I'll need to hack them off. Character's 19
> through 26 contain the IP address of the device. So 0a2202fc equals the
> IP address 10.34.2.252. I will have a list of all the devices I will
> need to compare against.
>
> So here is my plan:
>
> 1) Read the username
> 2) If the length of the username equals 34, send it into an if/else
> a) Read characters 19~26
> b) Comapre them to a(n) external file/array that has 300+ objects -
> Need help here
> c) If the value retrieved from 19~26 matches a 8 digit hex string
> stored in array/external file, truncate the last 8 characters of the
> username and store it as NEW_username.
> i.e. 0900000023000003780a2202fc0000229f will be modified to
> 0900000023000003780a2202fc
> 3) ELSE - do nothing and send the username through as presented.
>
> With my elementary knowledge of tcl, I got a start with this.
>
> proc ProcessBASIP {request response environ} {
> set username [ $request get User-Name ]
>
> if { [ string length $username ] == 34} {
> string equal
> string trimright
> # SETUP NEW USERNAME
> $environ put User-Name $NEW_username
> }
> else {
> $environ put User-Name $username
> }
>
> That's as far as I have gotten. I understand some computer languages,
> but regular expressions and tcl are a bit above me.
>
> Any help you can give me would be appreciated.
>
> Thanks,
> Don



proc EditUserName {username file_of_users} {
# file_of_users is name of file containing known
# IP addresses
#
if { [ string length $username ] <> 34} {
return $username ;# return original user id
}
else {
set a [split $username {}] ;# convert string to list
set b [lrange $a 18 25] ;# b now has user IP
set f [open $file_of_users]
set u [read $f] ;# u has the all known users
set u [split $u {}]
close $f
set flag [lsearch -exact $u $g] ;# -1 if no match
if {[$flag > -1]} {
return [lrange $a 0 25] ;# return truncated user id
}
else {
return $username ;# return original user id
}
}
}


From: Don Pich on
Hello Richard,

Thanks for the attempt. I have one question.

Is $g a globally defined variable, or is there a bit missing?
Can you use a file location for the filename? (i.e. /var/file_of_users)?

proc EditUserName {username file_of_users} {
# file_of_users is name of
file containing known # IP addresses
#
if { [ string length $username ] <> 34} {
return $username ;# return original user id }
else {
set a [split $username {}] ;# convert string to list set b
[lrange $a
18 25] ;# b now has user IP set f [open $file_of_users]
set u [read $f] ;# u has the all known users set u
[split
$u {}]
close $f
set flag [lsearch -exact $u $g] ;# -1 if no match if {[$flag >
-1]} {
return [lrange $a 0 25] ;# return truncated user id }
else {
return $username ;# return original user id }
}
}
From: Richard Owlett on
Don Pich wrote:
> Hello Richard,
>
> Thanks for the attempt. I have one question.
>
> Is $g a globally defined variable, or is there a bit missing?

The $g was a typo. It should have been $b .
[One of the reasons I tend to use long variable names. It makes
some typos very obvious to be typos.]

> Can you use a file location for the filename? (i.e. /var/file_of_users)?

Anything the open command accepts. I'm strictly a Windows(tm)
user without any familiarity with C or Linux conventions. So when
I post code I assume all problem specific information is stored
in a variable.

I've reformatted my code to solve the line wrap garbling that
occurred - There were tab characters in my post (probably not
good idea).

Convention in this group is to intersperse comments in quoted
text and/or to bottom post.

HTH

>
>
> proc EditUserName {username file_of_users} {
> # file_of_users is name of file containing known
> # IP addresses
> #
> if { [ string length $username ] <> 34} {
> return $username ;# return original user id
> }
> else {
> set a [split $username {}] ;# convert string to list
> set b [lrange $a 18 25] ;# b now has user IP
> set f [open $file_of_users]
> set u [read $f] ;# u has all known users
> set u [split $u {}]
> close $f
> set flag [lsearch -exact $u $b] ;# -1 if no match
> if {[$flag > -1]} {
> return [lrange $a 0 25] ;# return truncated user id
> }
> else {
> return $username ;# return original user id
> }
> }
> }
>
>
From: Aric Bills on
Let's pretend there's a text file at /var/file_of_users that contains
the IP addresses of interest, in hexidecimal format, where the
addresses are separated by some kind of whitespace (spaces, tabs, and/
or newlines). Let's read the contents of that file and put them in a
global variable called "user_list". We'll use a regular expression
that recognizes strings of non-space characters.

proc read_user_list {filename} {
variable user_list

set filehandle [open $filename r]
set contents [read $filehandle]
close $filehandle
set user_list [regexp -all -inline {\S+} $contents]
}

read_user_list /var/file_of_users

Now let's pretend the argument $username contains a user name as you
have described. Pretend $username is sanitized and that you've
already populated $user_list before calling the following procedure.
This procedure will return the first 26 characters of $username if
$username is 34 characters long and contains an IP address that is
listed in $user_list; otherwise it will return $username unchanged,
whether it was 34 characters long or not.

proc check_username {username} {
variable user_list

if {[string length $username] == 34} {
set ip_address [string range $username 18 25]
if {$ip_address in $user_list} {
return [string range $string 0 end-8]
}
}
return $username
}

If you're using an earlier version of Tcl than 8.5, then {$ip_address
in $user_list} won't work. Instead, use {[lsearch -exact $user_list
$ip_address] != -1}.
 |  Next  |  Last
Pages: 1 2 3 4
Prev: Compiling
Next: "open" issue in a new defined namespace