Parsing a DN from certificate in pem format (correct order) - certificate

I have seen a few posts related to parsing DN from a certificate in PEM format. I am writing a UNIX script that will read the pem files in a given path and spits out their corresponding Distinguished Name (DN) in the correct order. Created a simple script but the command that parses the pem file within the script is..
openssl x509 -in <file name.pem> -noout -subject
My confusion is when I run the above command, it spits the DN in this order starting with /C=US/ST=...but I know for a fact that the certificate DN starts with "CN=" which is exact reverse of what the command is spitting out. I am having a hard time trusting which command to run that gives me the exact order because I use that order to authenticate the user and if I onboard with the wrong order, requests will not be authorized and it defeats the purpose.

The order of the component of the DN is a matter of convention. The physical order inside the binary DER encoding is the one OpenSSL shows you here. OTOH the reverted order you expected is the one that a majority of tools use and that was normalized in RFC 2253.
This "/C=US/ST=..." format is the old OpenSSL one and now obsolete. If that's the one you get by default with OpenSSL, then you're using a very old version and should probably replace it with a more recent one.
In order to control how OpenSSL will display the subject, you need to use the -nameopt option. The value you can use are :
-nameopt rfc2253 : the order you wish, and the name will be "CN=xxx,OU=xxx,ST=xxx,C=FR" (no space, reverse order).
-nameopt oneline : the name will be "C = FR, ST = xxx , OU = xxx , CN = xxx".
-nameopt compat : the name will be "/C=US/ST=xxx/OU=xxx/CN=xxx" (without the space).
One more thing, if you compare the string of the DN to authenticate a client, the only way to get a reasonably reliable result is to use the exact same tool to generate it initially and when you verify it. As soon as a DN contains a less usual element, there's too many variations between tools to get the same string representation of the DN when not using the same one and the same version.

Related

Powershell: How to grab base64 value from attribute of SearchResultEntry object?

My goal is to fetch the published CRL of a CA from an LDAP connection.
I have a function to search the LDAP (not Active Directory!), which returns a System.DirectoryServices.Protocols.SearchResultEntryCollection as expected.
$results = LDAPsearch "$_LDAP_server`:$_LDAP_searchPort" "cn=$CA,$_LDAP_searchBase" '(&(certificateRevocationList=*))'
ForEach ($element in $results){
$element.Attributes['cn'].GetValues('string')
$element.Attributes['certificateRevocationList;binary'].GetValues('string')
}
The above properly reads the cn attribute value of each element returned, however the certificateRevocationList is returned in a strange format which does not correspond at all to the Base64 string I expect (e.g. the one that can be read if you export your data to an LDIF file or if you use the Linux ldapsearch command)...
How can I get the actual Base64 value ?
Unfortunately, you can only pass 'byte[]' or 'string' as parameter to the GetValues method (a 'Base64String' option here would be useful to me, but well...).
Current output below (where cn value is correctly written but not certificateRevocationList):
Retrieve the raw CRL as byte[], then convert to base64 yourself:
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')
$crlB64 = [Convert]::ToBase64String($crlBin)
Just adding the option I ended up using, much easier since my end-goal was actually to save the CRL as a file (and be able to parse it):
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')[0]
[IO.File]::WriteAllBytes("$_localDir\CRL_$CA.crl",$crlBin)
This writes the actual CRL file in DER format (can then easily be switched to PEM using certutil or openssl if needed). My initial idea was to construct a PEM-formatted CRL file from the Base64 value extracted, but I was looking way too far...
I'm leaving Mathias's response as the answer since he actually best answered my question ; I didn't specify that I wanted a CRL file in the end.

Powershell Byte Array input string invalid format

I've written a powershell script which changes the password of a local administrator that works well - It sets the password through a config file which contains the encrypted password and the aes key with which it was generated.
Its done the way described here: http://www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-2
Now we have a management suite which streamlines administration of windoze and linux, and somehow it doesnt pass the aes key right into the script.
If I try to execute it through the management suite, I get the following error:
Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte". Error: "Input string was not in a correct Format."
I think the problem is the difference between PS and the management suite to handle variables (Or the black magic Powershell does under the hood which the management suite doesnt). In the script im reading in the aes-key from config file to a variable, which contains the values that are in the error message, which represent the aes key.
Now my question is: How do i get powershell to recognize the aes key as a byte array?
I cannot simply do a get-content C:\aes_keyfile, which maybe does the right typecast or whatever, because the streamline process has its own methods, so what I get in the script is the following:
$blah = $blahobject.get_variable("aeskey")
$blah
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33
I cant do:
[byte[]]$new_blah = $blah - Error: Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte[]". Error: "Input string was not in a correct format.""
What is the correct format? How can I find out what it is current and what it expects?
Ok, i found it out, thanks to your hint with the type:
I had to split it at the comma, so the right way is:
[byte[]]$new_blah = $blah.split(",")
Now the decryption of the password works.
Thanks a lot :>

How do you search by DN in LDAP?

I'm pulling information about a user from LDAP. This includes directReports, which is in the full CN=cnBlah, OU=ouBlah, DC=dcBlah form. I'm trying to do another lookup to find info about the reportee.
So far the only way I've been able to actually find said user is to break out the CN= and set the remainder of the string as the base.
Is this the proper way of doing it? Or is there a way to search for an entry given the full DN?
Use the DN as the base object in the search and set the scope of the search to base.
Calling ldapsearch with the -f option would do pretty much what you want.
Save your first search results to a file, with only the value of the cn attribute. For example, your file would look like this :
users.txt:
user1
user2
cnBlah
john
jim
user883
Then call ldapsearch with a base that is high enough to encompass all users. This could be -b dc=users,dc=example,dc=com.
So if you saved your user list to a file named users.txt, your ldapsearch command line would look like this :
#I removed the hostname, port and authentification for clarity
ldapsearch -b "dc=users,dc=example,dc=com" -s sub "cn=%s" -f users.txt -LLL
Long lines will wrap at ~76 characters. Nothing that a pipe through perl -p00e 's/\r?\n //g' can't fix. (Or just add option -o ldif-wrap=no to your ldapsearch commandline.)
Closing the loop on this question, courtesy of https://www.openldap.org/lists/openldap-software/200503/msg00520.html
When you know the DN of an entry, there is no need to "search" for it all, just retrieve the entry directly:
ldapsearch -x -LLL -b "uid=droy,ou=people,dc=eclipse,dc=org"
So that answers the "how do you use ldapsearch to lookup() an item rather than search for it"

Maildrop: Filter mail by Date: header

I'm using getmail + maildrop + mutt + msmtp chain with messages stored in Maildir. Very big inbox bothers me, so i wanted to organize mail by date like that:
Maildir
|-2010.11->all messages with "Date: *, * Nov 2010 *"
|-2010.12->same as above...
|-2011.01
`-2011.02
I've googled much and read about mailfilter language, but still it is hard for me to write such filter. Maildrop's mailing list archives has almost nothing on this (as far as i scanned through it). There is some semi-solution on https://unix.stackexchange.com/questions/3092/organize-email-by-date-using-procmail-or-maildrop, but i don't like it, because i want to use "Date:" header and i want to sort by month like "YEAR.MONTH" in digits.
Any help, thoughts, links, materials will be appreciated.
Using mostly man pages, I came up with the following solution for use on Ubuntu 10.04. Create a mailfilter file called, for example, mailfilter-archive with the following content:
DEFAULT="$HOME/mail-archive"
MAILDIR="$DEFAULT"
# Uncomment the following to get logging output
#logfile $HOME/tmp/maildrop-archive.log
# Create maildir folder if it does not exist
`[ -d $DEFAULT ] || maildirmake $DEFAULT`
if (/^date:\s+(.+)$/)
{
datefile=`date -d "$MATCH1" +%Y-%m`
to $DEFAULT/$datefile
}
# In case the message is missing a date header, send it to a default mail file
to $DEFAULT/inbox
This uses the date command, taking the date header content as input (assuming it is in RFC-2822 format) and producing a formatted date to use as the mail file name.
Then execute the following on existing mail files to archive your messages:
cat mail1 mail2 mail3 mail4 | reformail -s maildrop mailfilter-archive
If the mail-archive contents look good, you could remove the mail1, mail2, mail3, mail4, etc. mail files.

How should I generate a random alphanumeric initial password for new users?

We have to automatically import a large list of users with some data into a running system.
For an initial password I want to update the list (csv format at the moment) with a random alphanumeric key (8 digits).
When inserting it with a special routine (which needs a csv file), the password (in this case the alphanumeric key) is stored as a md5 hash.
i.e. I generate a random alphanumeric key:
H2A5D39A -> MD5: 1642fccf791f15d137cf31282af79752
This way I want to create a list where authenticated users can ask me for their initial password (the alphanumeric key).
Do you have a better idea for a "secret" initial password?
How would you create the alphanumeric key in Perl?
P.S.: The "running system", not programmed by us, just allowes alphanumeric passwords (no special chars,...)
How would you create the alphanumeric key in Perl?
join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..8
I would probably use pwgen. It is great as it allows easy customization, and has the switch not to use ambiguous characters (think: I, l, 1, O, 0).
for example:
=> pwgen -c -n -B 8 50
shuFak9o peiCh3Oo ohPieng9 Vohh7zuu os3Theep aeV9nuo9 aexeik4B aeChoh9s
uth3eePu baePhu3o aiS3pahn iPie4itu We9zuphi xie3Chi3 yeiRoo7c fai3ITai
aCh9ohco Echuab7v Fu9ahCho Aevae4no Peethai9 AiJio3Pa aeNge9Fo baePh7Uy
Nai7shei eeMoh9en Zeibai4n eGe7yuch Jaek7nai aeZah7sh Chei4ua4 shoo9oG9
iu7Wohho aep7De4U Fong9fo3 AhneeP7U oxae7Yoh ahF4eim3 fahm9Aiw naoNg4ie
Chie4xua jix3Uvot aChei7ai diey4Shi Yur7ee4j eeJeo9ee Bou3ahmu kaeb4Cah
Eh4Eemae oD4phoo9
Anonymous's answer is very good, but, if you need a random string that conforms to some rules (such as at least one uppercase, one lowercase, and one number), you may want to look into String::Random.
Another module to consider is Data::Random
I just completed a review of the 12 modules on CPAN that can be used to generate random passwords:
http://blogs.perl.org/users/neilb/2011/08/random-password-generation.html
In short: if you want a pronounceable password, look at Crypt::YAPassGen,
otherwise go for App::Genpass.
App::Genpass avoids confusable characters and gives you better control (and defaults) than Data::Random or String::Random