Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Tuesday, December 26, 2006

setup openldap with ssl

The following url has a comprehensive description of configuring openldap server to use ssl:
http://www.openldap.org/pub/ksoper/OpenLDAP_TLS.html

Essentially, one can choose between basic server side ssl (one way authentication with a single self-signed root CA) setup and advanced client side ssl (two way authentication with server side root CA, private key, root CA signed server cert, client private key, root CA signed client certificate) setup. I have successfully setup ldaps using the documention in the provided URL. It also covers a bit of openssl usage which is nice. It certainly is an accomplishment after manually setting up openldap server/client using SSL and understanding what's going on behind the scene.

One thing learnt is that when certificate is involved, it's extremely important to use the right hostname or ipaddress but not both that matches what's recorded in certificates. openssl is a good tool to diagnose this sort of issues with its s_client and s_server emulation operations.

Friday, December 15, 2006

C++ typename and class are not equivalent in template programming

Contrary to the belief most C++ programmers held that class and typename can be used interchangeably or equivalent, there are few occasions that one must use typename instead of class. I think the rule of the thumb is 'use typename instead of class' in template programing, apart from the reason alone that typename by itself is more descriptive of the intention than class.

#include < iostream>

template< typename t =" Val_"> class Cont_{ // class is not allowed.
Val_ sum(Cont_& c) {
Val_ sum = 0;
for (typename Cont_::iterator i = c.begin(); i < c.end(); ++i)
sum += *i;
return sum;
}

template< typename T>
class Test {
T t[3];
public:
typedef T* iterator;

Test() { t[0] = t[1] = t[2] = 1; }
T* begin() {return t;}
T* end() {return t+3;}
};


int main() {
Test< int> test;
std::cout << sum(test);
}
#include < iostream>

template< typename t =" Val_"> class Cont_{ //HERE
Val_ sum(Cont_< val_>& c) {
Val_ sum = 0;
for (typename Cont_< val_>::iterator i = c.begin(); i < c.end(); ++i)
sum += *i;
return sum;
}

template< typename>
class Test {
T t[3];
public:
typedef T* iterator;

Test() { t[0] = t[1] = t[2] = 1; }
T* begin() {return t;}
T* end() {return t+3;}
};


int main() {
Test< int> test;
std::cout << sum(test);
}

C/C++ local and global static variables

There appears to be some confusion in people's mind how static variables operate. Quote from CLC++:

The implication of this is that the compiler has to generate
a hidden static flag to prevent re-initialization, and that flag
has to be checked every time control passes the local static
definition.The implication of this is that the compiler has to generate
a hidden static flag to prevent re-initialization, and that flag
has to be checked every time control passes the local static
definition.

As will be demonstrated by the following code, local static variables are usualy implemented exactly the same as global static variables,

# more static_t.c
static int si;

void foo(int x){
static int z;
z = z + x;
si = x;
return;
}

#gcc -c static_t.c
[feiliu@maple c]$ objdump -d static_t1a.o

static_t1a.o: file format elf32-i386

Disassembly of section .text:

00000000 :
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: a1 00 00 00 00 mov 0x0,%eax <------------ RELOCATABLE RECORD
8: 03 45 08 add 0x8(%ebp),%eax
b: a3 00 00 00 00 mov %eax,0x0 <------------ RELOCATABLE RECORD
10: 8b 45 08 mov 0x8(%ebp),%eax
13: a3 04 00 00 00 mov %eax,0x4 <------------ RELOCATABLE RECORD
18: 5d pop %ebp
19: c3 ret
[feiliu@maple c]$ objdump -x static_t1a.o

static_t1a.o: file format elf32-i386
static_t1a.o
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000001a 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000050 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000008 00000000 00000000 00000050 2**2
ALLOC
3 .comment 0000002d 00000000 00000000 00000050 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 0000007d 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 static_t1a.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l O .bss 00000004 z.1281
00000004 l O .bss 00000004 si
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000001a foo


RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000004 R_386_32 .bss
0000000c R_386_32 .bss
00000014 R_386_32 .bss

The compiler has generated identical machine code for the both global and static variables and the relocatable records indicate that their storage segment is .bss segment. Refer to a previous article on this subject about how static variables are implemented by compilers/linkers.

Thursday, December 14, 2006

C++ rules of the thumb: choose the proper function parameter prototype

Quote from CLC++:

When designing a function, we can make the parameter type T, const T&,
T&, const T*, or T*. The OP asked how to decide between the five
options. I'm interested in your answer. How do you decide between them?
Can your formulate your decision process as an algorithm?When designing a function, we can make the parameter type T, const T&,
T&, const T*, or T*. The OP asked how to decide between the five
options. I'm interested in your answer. How do you decide between them?

if( there does not need to be a way to express "no value" )
{
if( parameter is just an in parameter )
{
if( the type is sufficiently small so the overhead of
copying is less than the overhead of accessing
it through a pointer)
{
pass by value
}
else
{
if( the function is C++ only)
pass by const reference
else // it needs to be callable from C
pass by const pointer
}
}
else
{ // parameter is out or inout
if( the function is C++ only )
pass by reference
else
pass by pointer
}
}
else
{ // there needs to be a way to express "no value"
if( parameter is an in parameter )
pass by const pointer
else
pass by pointer
}

C++ const reference and template generic programming

Consider that you are required to write a min function (not macro), in C++ the best approach would be to use a template function to write the min function once for all:

inline template < typename>
T min(T const& a, T const& b) { return a < b? a: b; }

However there is a subtle issue here with const reference argument when it comes to character array literals. To quote Noah Roberts from CLC++:

The problem has to do with how character arrays get resolved per

reference vs. value. For example you wouldn't be able to pass two
string literals of different length to that function:

char * x = min("hello", "hell");

Nope...won't work (not according to the book anyway).

Reason, becasue it is reference semantics it attempts to pass char[6]&
as first and char[5]& as second parameters...can't happen.

The way to fix this is to override for char*, which you have to do
anyway:

template<>
char* min(char* l, char* r) { ... do strcmp stuff...}

So, there is no "problem" to speak of, just something to be aware of.

Tuesday, December 12, 2006

KERBROS based authentication

An overview of kerberos authentication method is given by wikipedia. Following REDHAT's administrator's guide on setting up KERBEROS server/client, one can start testing kerberos authentication. A commone issue encountered I imagine is this error message in log:

Dec 12 15:09:26 maple.netilla.com krb5kdc[29641](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.34: CLIENT_NOT_FOUND: feiliu@NETILLA.COM for krbtgt/NETILLA.COM@NETILLA.COM, Client not found in Kerberos database
Dec 12 15:09:26 maple.netilla.com krb5kdc[29641](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.34: CLIENT_NOT_FOUND: feiliu@NETILLA.COM for krbtgt/NETILLA.COM@NETILLA.COM, Client not found in Kerberos database

==> /var/log/krb5kdc.log <==
Dec 12 15:15:55 maple.netilla.com krb5kdc[29641](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.34: ISSUE: authtime 1165954555, etypes {rep=16 tkt=16 ses=16}, feiliu@NETILLA.COM for krbtgt/NETILLA.COM@NETILLA.COM
Dec 12 15:15:55 maple.netilla.com krb5kdc[29641](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.34: ISSUE: authtime 1165954555, etypes {rep=16 tkt=16 ses=16}, feiliu@NETILLA.COM for krbtgt/NETILLA.COM@NETILLA.COM

'Client not found in Kerberos database' is a result of missing principle in KDC database. Again, ethereal or tcpdump are invaluable to diagnose network traffic pattern and figure out what's happening. At linux console,
# kinit feiliu/admin@NETILLA.COM
Password for feiliu/admin@NETILLA.COM:
[root@maple ~]# kadmin
Authenticating as principal feiliu/admin@NETILLA.COM with password.
Password for feiliu/admin@NETILLA.COM:
kadmin: ?
Available kadmin requests:

add_principal, addprinc, ank
Add principal
delete_principal, delprinc
Delete principal
modify_principal, modprinc
Modify principal
change_password, cpw Change password
get_principal, getprinc Get principal
list_principals, listprincs, get_principals, getprincs
List principals
add_policy, addpol Add policy
modify_policy, modpol Modify policy
delete_policy, delpol Delete policy
get_policy, getpol Get policy
list_policies, listpols, get_policies, getpols
List policies
get_privs, getprivs Get privileges
ktadd, xst Add entry(s) to a keytab
ktremove, ktrem Remove entry(s) from a keytab
lock Lock database exclusively (use with extreme caution!)
unlock Release exclusive database lock
list_requests, lr, ? List available requests.
quit, exit, q Exit program.
kadmin: getprincs
K/M@NETILLA.COM
feiliu/admin@NETILLA.COM
feiliu/firewood.netilla.com@NETILLA.COM
host/firewood.netilla.com@NETILLA.COM
kadmin/admin@NETILLA.COM
kadmin/changepw@NETILLA.COM
kadmin/history@NETILLA.COM
kadmin/maple@NETILLA.COM
krbtgt/NETILLA.COM@NETILLA.COM

which suggests that the missing principle 'feiliu/NETILLA.COM@NETILLA.COM' is indeed not in the KDC database. Create this entry:
kadmin: addprinc feiliu@NETILLA.COM
WARNING: no policy specified for feiliu@NETILLA.COM; defaulting to no policy
Enter password for principal "feiliu@NETILLA.COM":
Re-enter password for principal "feiliu@NETILLA.COM":
Principal "feiliu@NETILLA.COM" created.
kadmin.local: getprincs
K/M@NETILLA.COM
feiliu/NETILLA.COM@NETILLA.COM
feiliu/admin@NETILLA.COM
feiliu/firewood.netilla.com@NETILLA.COM
feiliu@NETILLA.COM
host/firewood.netilla.com@NETILLA.COM
kadmin/admin@NETILLA.COM
kadmin/changepw@NETILLA.COM
kadmin/history@NETILLA.COM
kadmin/maple@NETILLA.COM
krbtgt/NETILLA.COM@NETILLA.COM

Try again from kerbros client, authentication is successful with valid credentials information in the kerbros log.

Use ssldump to decrypt/view SSL/TLS encrypted network packets

With widespread use of SSL/TLS encryption of network traffic, tcpdump/ethereal often are not as useful as they used to be. SSLDUMP is a tool designed to decrypt and display encrypted network traffic. First obtain the private key used during the communication, capture a packet using tcpdump or do a live session (if host computer is fast):

ssldump -k priv_key -r /scratch/sslpkt2 -i eth0 -d

Monday, December 04, 2006

Dell Inspiron 1501 ethernet driver and Fedora Core 6 issues

Dell website does not have 64 bit broadcom ethernet 4401 driver for AMD Turion 64 laptop (Insipron 1501), this driver can be downloaded from broadcome website directly: http://www.broadcom.com/support/ethernet_nic/4401.php

There are similar issues (not as critical) with model and chipset drivers which I suppose have to be downloaded from OEM vendors directly.

Fedora core 6 64bit seems to have a problem with the SATA hard drive used, this needs further investigation.

Saturday, December 02, 2006

configure linux samba server to interoperate with different versions of windows

# Password Level allows matching of _n_ characters of the password for
# all combinations of upper and lower case.
password level = 20
username level = 20

# You may wish to use password encryption. Please read
# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation.
# Do not enable this option unless you have read those documents
encrypt passwords = yes
smb passwd file = /etc/samba/smbpasswd

# Unix users can map to different SMB User names
username map = /etc/smbusers

Friday, December 01, 2006

Be careful with openlog/syslog library calls

#include

void foo(){
openlog("FOO", LOG_PID|LOG_PERROR, LOG_USER);
syslog(LOG_INFO, "logging from foo");
}

int main(void){
openlog("MAIN", LOG_PID|LOG_PERROR, LOG_AUTH);
foo();
syslog(LOG_INFO, "logging from MAIN");
}

Ever wonder why sometimes syslog secretly sends logging message to the wrong facility behind your back? It appears openlog call has a process wide effect,

#include

void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);

Facility number can be changed at any place in the source code by a call to openlog. Any subsequent call to syslog will use the new facility number specified. In my opinion, it's a bad form of programming to use syslog directly in library code. Watch out for this bug when you use syslog.