Parse x.500 DN and change order displayed

S

SecureIT

I am trying to change this

"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"

to this:

"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

There are about 2000 entries like this and I need to have them all
displayed with serialNumber first, and cn last then the rest of the
DN, the names and serialNumbers are all unique to each entry.

Any help would be great

Thanks,
gotsecure
 
U

Uri Guttman

S> I am trying to change this
S> "cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"

S> to this:

S> "serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

S> There are about 2000 entries like this and I need to have them all
S> displayed with serialNumber first, and cn last then the rest of the
S> DN, the names and serialNumbers are all unique to each entry.

are all the entries separated by +? how many are there (you show only 2)?

if it is always + then you can just split the lines, grab out the cn one
(use grep) and also filter out the rest. then order them as you
want. call join '+' to rebuild the line. it can also be done with a hash
but that is about the same amount of code.

uri
 
H

Hallvard B Furuseth

SecureIT said:
I am trying to change this
"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"
to this:
"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

Without escape sequences like "\," and "\+" in the DNs (if that's
allowed anyway, I don't remember the details of X.500 Dn syntax), this
moves serialNumber first in each RDN:

s/(^|,)([^,]*)\+(serialNumber=[^+,]*)(?=[+,])/$1$3+$2/gi;
die "didn't catch all 'foo+serialNumber's" if /\+serialNumber=/i;
 
S

SecureIT

SecureIT said:
I am trying to change this
"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"
to this:
"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

Without escape sequences like "\," and "\+" in the DNs (if that's
allowed anyway, I don't remember the details of X.500 Dn syntax), this
moves serialNumber first in each RDN:

s/(^|,)([^,]*)\+(serialNumber=[^+,]*)(?=[+,])/$1$3+$2/gi;
die "didn't catch all 'foo+serialNumber's" if /\+serialNumber=/i;

That worked great, thanks so much. Just ran it and all 2000 DN's are
properly formatted now.

-G
 
S

szr

Hallvard said:
SecureIT said:
I am trying to change this
"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"
to this:
"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

Without escape sequences like "\," and "\+" in the DNs (if that's
allowed anyway, I don't remember the details of X.500 Dn syntax), this
moves serialNumber first in each RDN:

s/(^|,)([^,]*)\+(serialNumber=[^+,]*)(?=[+,])/$1$3+$2/gi;
die "didn't catch all 'foo+serialNumber's" if /\+serialNumber=/i;

Using this regex will take care of \, and \+ escapes:

s/(^|(?<!\\),)((?:[^,]|\\,)*)\+(serialNumber=(?:[^+,]|\\[+,])*)(?=(?<!\\)[+,])/$1$3+$2/gi;


Matches:

my $dn = "cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US";
$dn =~ s/
(^|(?<!\\),) ((?:[^,]|\\,)*) \+
(serialNumber = (?:[^+,] | \\[+,])*)
(?=(?<!\\)[+,])
/$1$3+$2/gix;
print $dn;


__OUTPUT__
serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US


And:

my $dn = "cn=Smith\\, Bob+serialNumber=CR01312\\+0080827,o=ICM,c=US";
$dn =~ s/
(^|(?<!\\),) ((?:[^,]|\\,)*) \+
(serialNumber = (?:[^+,] | \\[+,])*)
(?=(?<!\\)[+,])
/$1$3+$2/gix;
print $dn;


__OUTPUT__
serialNumber=CR01312\+0080827+cn=Smith\, Bob,o=ICM,c=US


Hope this helps.
 
U

Uri Guttman

S> I am trying to change this
S> "cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"S> There are about 2000 entries like this and I need to have them all
S> displayed with serialNumber first, and cn last then the rest of the
S> DN, the names and serialNumbers are all unique to each entry.
d> Am I missing something? Why can't (or shouldn't) he do this?
d> $entry =~ s/(cn[^+]+)\+([^,]+)(.*)$/$2+$1$3/;

d> Is it less efficient in some way?

that assumes the serial number is in slot 1 ($2) and i wouldn't make
that assumption. the other regex answers match the serial part and not
the cn part like you do. i was thinking about a more flexible solution
which would allow any reordering of many parts and no regex could do
that. hence my idea about split and joining in the desired order.

uri
 
H

Hallvard B Furuseth

szr said:
Hallvard said:
SecureIT said:
I am trying to change this
"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"
to this:
"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

Without escape sequences like "\," and "\+" in the DNs (if that's
allowed anyway, I don't remember the details of X.500 Dn syntax), this
moves serialNumber first in each RDN:

s/(^|,)([^,]*)\+(serialNumber=[^+,]*)(?=[+,])/$1$3+$2/gi;
die "didn't catch all 'foo+serialNumber's" if /\+serialNumber=/i;

Using this regex will take care of \, and \+ escapes:

s/(^|(?<!\\),)((?:[^,]|\\,)*)\+(serialNumber=(?:[^+,]|\\[+,])*)(?=(?<!\\)[+,])/$1$3+$2/gi;

Nope... not if I can create naughty "cn" values:

this: cn=a\\,cn=b+serialNumber=c,o=x
becomes serialNumber=c+cn=a\\,cn=b,o=x
instead of cn=a\\,serialNumber=c+cn=b,o=x

this: cn=b\+serialNumber=c,o=x
contains no serialNumber attribute but is modified anyway.

Not that it matters much when the OP's problem is solved anyway.
Just pointing out that once you are going to accept things that need
nontrivial parsing like escape sequences, you have to be careful to
parse it correctly. Though my variant missed out too, it should
have ended with (?=$|[+,]) to cover the last component as well.
 
S

szr

Hallvard said:
szr said:
Hallvard said:
SecureIT writes:
I am trying to change this
"cn=Bob Smith+serialNumber=CR013120080827,o=ICM,c=US"
to this:
"serialNumber=CR013120080827+cn=Bob Smith,o=ICM,c=US"

Without escape sequences like "\," and "\+" in the DNs (if that's
allowed anyway, I don't remember the details of X.500 Dn syntax),
this moves serialNumber first in each RDN:

s/(^|,)([^,]*)\+(serialNumber=[^+,]*)(?=[+,])/$1$3+$2/gi;
die "didn't catch all 'foo+serialNumber's" if /\+serialNumber=/i;

Using this regex will take care of \, and \+ escapes:

s/(^|(?<!\\),)((?:[^,]|\\,)*)\+(serialNumber=(?:[^+,]|\\[+,])*)(?=(?<!\\)[+,])/$1$3+$2/gi;

Nope... not if I can create naughty "cn" values:

this: cn=a\\,cn=b+serialNumber=c,o=x
becomes serialNumber=c+cn=a\\,cn=b,o=x
instead of cn=a\\,serialNumber=c+cn=b,o=x

this: cn=b\+serialNumber=c,o=x
contains no serialNumber attribute but is modified anyway.

Not that it matters much when the OP's problem is solved anyway.
Just pointing out that once you are going to accept things that need
nontrivial parsing like escape sequences, you have to be careful to
parse it correctly. Though my variant missed out too, it should
have ended with (?=$|[+,]) to cover the last component as well.

Well, my example assumed proper checks would already by done by the time
it was invoked. But good points nonetheless.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top