]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/zone2ldap.cc
2 * PowerDNS BIND Zone to LDAP converter
3 * Copyright (C) 2003 Norbert Sendetzky
4 * Copyright (C) 2007 bert hubert
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * the Free Software Foundation
10 * Additionally, the license of this program contains a special
11 * exception which allows to distribute the program in binary form when
12 * it is linked against OpenSSL.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "arguments.hh"
34 #include "bindparserclasses.hh"
36 #include <boost/function.hpp>
37 #include "dnsrecords.hh"
40 #include "zoneparser-tng.hh"
50 unsigned int g_domainid
;
54 map
<DNSName
,bool> g_objects
;
55 map
<string
, bool> g_entries
;
56 map
<DNSName
,bool> g_recorddata
;
57 map
<DNSName
, map
<string
, bool> > g_recordttl
;
59 std::string
encode_non_ascii( const std::string
&input
) {
60 std::ostringstream out
;
62 for ( auto i
: input
) {
63 if ( (unsigned char)i
> 0x7F )
64 out
<< '\\' << int( (unsigned char)i
);
72 static void callback_simple( unsigned int domain_id
, const DNSName
&domain
, const string
&qtype
, const string
&content
, int ttl
)
76 if( ! domain
.isPartOf(g_zonename
) )
78 cerr
<< "Domain '" << domain
<< "'' not part of '" << g_zonename
<< "'"<< endl
;
82 host
= domain
.makeRelative(g_zonename
);
84 if( g_pdnsinfo
&& qtype
== "SOA" ) {
85 cout
<< "dn: ou=" << domain
<< "," << g_metadatadn
<< endl
;
86 cout
<< "changetype: add" << endl
;
87 cout
<< "objectclass: organizationalUnit" << endl
;
88 cout
<< "ou: " << domain
.toStringNoDot() << endl
;
92 std::string stripped
=stripDot(content
);
93 std::string rrvalue
= stripped
+ ((stripped
.empty() || stripped
[stripped
.size()-1]==' ') ? "." : "");
94 std::string dn
= "dc=";
95 if( host
.countLabels() ) { dn
+= host
.toStringNoDot() + ",dc="; }
96 dn
+= g_zonename
.toStringNoDot() + "," + g_basedn
;
97 cout
<< "dn: " << dn
<< endl
;
99 if( host
.countLabels() == 0 ) { host
= g_zonename
; }
103 g_entries
[dn
] = true;
104 g_recorddata
[domain
] = true;
106 cout
<< "changetype: add" << endl
;
107 cout
<< "objectclass: dnsdomain2" << endl
;
108 cout
<< "objectclass: domainrelatedobject" << endl
;
109 cout
<< "objectclass: PdnsRecordData" << endl
;
110 if( g_pdnsinfo
&& qtype
== "SOA" ) {
111 cout
<< "objectclass: PdnsDomain" << endl
;
112 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
114 cout
<< "dc: " << host
.toStringNoDot() << endl
;
115 if( g_dnsttl
) { cout
<< "dnsttl: " << ttl
<< endl
; }
116 cout
<< "associateddomain: " << domain
.toStringNoDot() << endl
;
120 cout
<< "changetype: modify" << endl
;
121 if ( !g_recorddata
[domain
] ) {
122 g_recorddata
[domain
] = true;
123 cout
<< "add: objectClass" << endl
;
124 cout
<< "objectClass: PdnsRecordData" << endl
;
127 if ( !g_recordttl
.count( domain
) || !g_recordttl
[domain
].count( qtype
) ) {
128 g_recordttl
[domain
][qtype
] = true;
129 cout
<< "add: PdnsRecordTTL" << endl
;
130 cout
<< "PdnsRecordTTL: " << qtype
<< "|" << ttl
<< endl
;
133 cout
<< "add: " << qtype
<< "Record" << endl
;
135 cout
<< qtype
<< "Record: " << rrvalue
<< endl
<< endl
;
140 static void callback_tree( unsigned int domain_id
, const DNSName
&domain
, const string
&qtype
, const string
&content
, int ttl
)
145 vector
<string
> parts
;
147 stringtok( parts
, domain
.toStringNoDot(), "." );
148 if( parts
.empty() ) { return; }
150 for( i
= parts
.size() - 1; i
> 0; i
-- )
152 net
.prependRawLabel(parts
[i
]);
153 dn
= "dc=" + parts
[i
] + "," + dn
;
155 if( !g_objects
[net
] )
157 g_objects
[net
] = true;
159 cout
<< "dn: " << dn
<< g_basedn
<< endl
;
160 cout
<< "changetype: add" << endl
;
161 cout
<< "objectclass: dnsdomain2" << endl
;
162 cout
<< "objectclass: domainrelatedobject" << endl
;
163 cout
<< "dc: " << parts
[i
] << endl
;
164 cout
<< "associateddomain: " << net
.toStringNoDot() << endl
<< endl
;
169 if( g_pdnsinfo
&& qtype
== "SOA" ) {
170 cout
<< "dn: ou=" << domain
<< "," << g_metadatadn
<< endl
;
171 cout
<< "changetype: add" << endl
;
172 cout
<< "objectclass: organizationalUnit" << endl
;
173 cout
<< "ou: " << domain
.toStringNoDot() << endl
;
177 std::string stripped
=stripDot(content
);
178 std::string rrvalue
= stripped
+ ((stripped
.empty() || stripped
[stripped
.size()-1]==' ') ? "." : "");
179 cout
<< "dn: " << "dc=" << parts
[0] << "," << dn
<< g_basedn
<< endl
;
181 if( !g_objects
[domain
] )
183 g_objects
[domain
] = true;
184 g_recorddata
[domain
] = true;
186 cout
<< "changetype: add" << endl
;
187 cout
<< "objectclass: dnsdomain2" << endl
;
188 cout
<< "objectclass: domainrelatedobject" << endl
;
189 cout
<< "objectclass: PdnsRecordData" << endl
;
190 if( g_pdnsinfo
&& qtype
== "SOA" ) {
191 cout
<< "objectclass: PdnsDomain" << endl
;
192 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
194 cout
<< "dc: " << parts
[0] << endl
;
195 if( g_dnsttl
) { cout
<< "dnsttl: " << ttl
<< endl
; }
196 cout
<< "associateddomain: " << domain
.toStringNoDot() << endl
;
200 cout
<< "changetype: modify" << endl
;
201 if( g_pdnsinfo
&& qtype
== "SOA" ) {
202 cout
<< "add: objectclass" << endl
;
203 cout
<< "objectclass: PdnsDomain" << endl
;
205 cout
<< "add: PdnsDomainId" << endl
;
206 cout
<< "PdnsDomainId: " << domain_id
<< endl
;
209 if ( !g_recorddata
[domain
] ) {
210 g_recorddata
[domain
] = true;
211 cout
<< "add: objectClass" << endl
;
212 cout
<< "objectClass: PdnsRecordData" << endl
;
215 if ( !g_recordttl
.count( domain
) || !g_recordttl
[domain
].count( qtype
) ) {
216 g_recordttl
[domain
][qtype
] = true;
217 cout
<< "add: PdnsRecordTTL" << endl
;
218 cout
<< "PdnsRecordTTL: " << qtype
<< "|" << ttl
<< endl
;
221 cout
<< "add: " << qtype
<< "Record" << endl
;
223 cout
<< qtype
<< "Record: " << rrvalue
<< endl
<< endl
;
228 int main( int argc
, char* argv
[] )
231 vector
<string
> parts
;
236 std::ios_base::sync_with_stdio( false );
238 args
.setCmd( "help", "Provide a helpful message" );
239 args
.setCmd( "version", "Print the version" );
240 args
.setSwitch( "verbose", "Verbose comments on operation" ) = "no";
241 args
.setSwitch( "resume", "Continue after errors" ) = "no";
242 args
.setSwitch( "dnsttl", "Add dnsttl attribute to every entry" ) = "no";
243 args
.setSwitch( "pdns-info", "Add the PDNS domain info attributes (this mandates setting --metadata-dn)" ) = "no";
244 args
.set( "named-conf", "Bind 8 named.conf to parse" ) = "";
245 args
.set( "zone-file", "Zone file to parse" ) = "";
246 args
.set( "zone-name", "Specify a zone name if zone is set" ) = "";
247 args
.set( "basedn", "Base DN to store objects below" ) = "ou=hosts,o=mycompany,c=de";
248 args
.set( "layout", "How to arrange entries in the directory (simple or as tree)" ) = "simple";
249 args
.set( "domainid", "Domain ID of the first domain found (incremented afterwards)" ) = "1";
250 args
.set( "metadata-dn", "DN under which to store the domain metadata" ) = "";
252 args
.parse( argc
, argv
);
254 if(args
.mustDo("version")) {
255 cerr
<<"zone2ldap "<<VERSION
<<endl
;
259 if( args
.mustDo( "help" ) )
261 cout
<< "Syntax:" << endl
<< endl
;
262 cout
<< args
.helpstring() << endl
;
268 cerr
<< "Syntax:" << endl
<< endl
;
269 cerr
<< args
.helpstring() << endl
;
273 g_basedn
= args
["basedn"];
274 g_dnsttl
= args
.mustDo( "dnsttl" );
275 typedef boost::function
<void(unsigned int, const DNSName
&, const string
&, const string
&, int)> callback_t
;
276 callback_t callback
= callback_simple
;
277 if( args
["layout"] == "tree" )
279 callback
=callback_tree
;
282 if ( args
.mustDo( "pdns-info" ) ) {
284 if( args
["metadata-dn"].empty() ) {
285 cerr
<< "You must set --metadata-dn when using --pdns-info" << endl
;
288 g_metadatadn
= args
["metadata-dn"];
294 if ( !args
["domainid"].empty() )
295 g_domainid
= pdns_stou( args
["domainid"] );
299 if( !args
["named-conf"].empty() )
301 BP
.setVerbose( args
.mustDo( "verbose" ) );
302 BP
.parse( args
["named-conf"] );
303 // ZP.setDirectory( BP.getDirectory() );
304 const vector
<BindDomainInfo
> &domains
= BP
.getDomains();
306 for(const auto& i
: domains
)
308 if(i
.type
!="master" && i
.type
!="slave") {
309 cerr
<<" Warning! Skipping '"<<i
.type
<<"' zone '"<<i
.name
<<"'"<<endl
;
314 if( i
.name
!= g_rootdnsname
&& i
.name
!= DNSName("localhost") && i
.name
!= DNSName("0.0.127.in-addr.arpa") )
316 cerr
<< "Parsing file: " << i
.filename
<< ", domain: " << i
.name
<< endl
;
318 ZoneParserTNG
zpt(i
.filename
, i
.name
, BP
.getDirectory());
319 DNSResourceRecord rr
;
321 callback(g_domainid
, rr
.qname
, rr
.qtype
.getName(), encode_non_ascii(rr
.content
), rr
.ttl
);
322 if( rr
.qtype
== QType::SOA
)
327 catch( PDNSException
&ae
)
329 cerr
<< "Fatal error: " << ae
.reason
<< endl
;
330 if( !args
.mustDo( "resume" ) )
339 if( args
["zone-file"].empty() || args
["zone-name"].empty() )
341 cerr
<< "Error: At least zone-file and zone-name are required" << endl
;
345 g_zonename
= DNSName(args
["zone-name"]);
346 ZoneParserTNG
zpt(args
["zone-file"], g_zonename
);
347 DNSResourceRecord rr
;
349 callback(g_domainid
, rr
.qname
, rr
.qtype
.getName(), encode_non_ascii(rr
.content
), rr
.ttl
);
350 if ( rr
.qtype
== QType::SOA
)
355 catch( PDNSException
&ae
)
357 cerr
<< "Fatal error: " << ae
.reason
<< endl
;
360 catch( std::exception
&e
)
362 cerr
<< "Died because of STL error: " << e
.what() << endl
;
367 cerr
<< "Died because of unknown exception" << endl
;