1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 
31 #include "ldapaccess.hxx"
32 #include "ldapuserprofilebe.hxx"
33 #include <osl/file.hxx>
34 #include <osl/module.hxx>
35 #include <osl/process.h>
36 #include <rtl/ustrbuf.hxx>
37 #include <rtl/byteseq.h>
38 
39 #ifndef INCLUDED_RTL_INSTANCE_HXX_
40 #include <rtl/instance.hxx>
41 #endif
42 #include <com/sun/star/beans/NamedValue.hpp>
43 #include <com/sun/star/beans/Optional.hpp>
44 #include <osl/security.hxx>
45 
46 //==============================================================================
47 namespace extensions { namespace config { namespace ldap {
48 
49 LdapUserProfileBe::LdapUserProfileBe( const uno::Reference<uno::XComponentContext>& xContext)
50 : LdapProfileMutexHolder(),
51   BackendBase(mMutex)
52 {
53     LdapDefinition aDefinition;
54     rtl::OUString loggedOnUser;
55 
56     // This whole rigmarole is to prevent an infinite recursion where reading
57     // the configuration for the backend would create another instance of the
58     // backend, which would try and read the configuration which would...
59     {
60         osl::Mutex & aInitMutex = rtl::Static< osl::Mutex, LdapUserProfileBe >::get();
61         osl::MutexGuard aInitGuard(aInitMutex);
62 
63         static bool bReentrantCall; // = false
64         OSL_ENSURE(!bReentrantCall, "configuration: Ldap Backend constructor called reentrantly - probably a registration error.");
65 
66         if (!bReentrantCall)
67         {
68             try
69             {
70                 bReentrantCall = true ;
71                 if (!readLdapConfiguration(
72                         css::uno::Reference< css::lang::XMultiServiceFactory >(
73                             xContext->getServiceManager(),
74                             css::uno::UNO_QUERY_THROW),
75                         &aDefinition, &loggedOnUser))
76                 {
77                     throw css::uno::RuntimeException(
78                         rtl::OUString::createFromAscii("LdapUserProfileBe- LDAP not configured"),
79                         NULL);
80                 }
81 
82                 bReentrantCall = false ;
83             }
84             catch (...)
85             {
86                 bReentrantCall = false;
87                 throw;
88             }
89         }
90     }
91 
92     LdapConnection connection;
93     connection.loadModule();
94     connection.connectSimple(aDefinition);
95     connection.getUserProfile(loggedOnUser, &data_);
96 }
97 //------------------------------------------------------------------------------
98 LdapUserProfileBe::~LdapUserProfileBe()
99 {
100 }
101 //------------------------------------------------------------------------------
102 
103 bool LdapUserProfileBe::readLdapConfiguration(
104     css::uno::Reference< css::lang::XMultiServiceFactory > const & factory,
105     LdapDefinition * definition, rtl::OUString * loggedOnUser)
106 {
107     OSL_ASSERT(factory.is() && definition != 0 && loggedOnUser != 0);
108     const rtl::OUString kConfigurationProviderService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")) ;
109     const rtl::OUString kReadOnlyViewService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")) ;
110     const rtl::OUString kComponent( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.LDAP/UserDirectory"));
111     const rtl::OUString kServerDefiniton(RTL_CONSTASCII_USTRINGPARAM ("ServerDefinition"));
112     const rtl::OUString kServer(RTL_CONSTASCII_USTRINGPARAM ("Server"));
113     const rtl::OUString kPort(RTL_CONSTASCII_USTRINGPARAM("Port"));
114     const rtl::OUString kBaseDN(RTL_CONSTASCII_USTRINGPARAM("BaseDN"));
115     const rtl::OUString kUser(RTL_CONSTASCII_USTRINGPARAM("SearchUser"));
116     const rtl::OUString kPassword(RTL_CONSTASCII_USTRINGPARAM("SearchPassword"));
117     const rtl::OUString kUserObjectClass(RTL_CONSTASCII_USTRINGPARAM("UserObjectClass"));
118     const rtl::OUString kUserUniqueAttr(RTL_CONSTASCII_USTRINGPARAM("UserUniqueAttribute"));
119 
120 	uno::Reference< XInterface > xIface;
121     try
122     {
123         uno::Reference< lang::XMultiServiceFactory > xCfgProvider(
124                                                         factory->createInstance(kConfigurationProviderService),
125                                                         uno::UNO_QUERY);
126 	    OSL_ENSURE(xCfgProvider.is(),"LdapUserProfileBe: could not create the configuration provider");
127 	    if (!xCfgProvider.is())
128             return false;
129 
130         css::beans::NamedValue aPath(rtl::OUString::createFromAscii("nodepath"), uno::makeAny(kComponent) );
131 
132         uno::Sequence< uno::Any > aArgs(1);
133         aArgs[0] <<=  aPath;
134 
135         xIface = xCfgProvider->createInstanceWithArguments(kReadOnlyViewService, aArgs);
136 
137         uno::Reference<container::XNameAccess > xAccess(xIface, uno::UNO_QUERY_THROW);
138         xAccess->getByName(kServerDefiniton) >>= xIface;
139 
140         uno::Reference<container::XNameAccess > xChildAccess(xIface, uno::UNO_QUERY_THROW);
141 
142         if (!getLdapStringParam(xChildAccess, kServer, definition->mServer))
143             return false;
144         if (!getLdapStringParam(xChildAccess, kBaseDN, definition->mBaseDN))
145             return false;
146 
147         definition->mPort=0;
148         xChildAccess->getByName(kPort) >>= definition->mPort ;
149 	    if (definition->mPort == 0)
150 		    return false;
151 
152         if (!getLdapStringParam(xAccess, kUserObjectClass, definition->mUserObjectClass))
153             return false;
154         if (!getLdapStringParam(xAccess, kUserUniqueAttr, definition->mUserUniqueAttr))
155             return false;
156 
157         getLdapStringParam(xAccess, kUser, definition->mAnonUser);
158         getLdapStringParam(xAccess, kPassword, definition->mAnonCredentials);
159     }
160     catch (uno::Exception & e)
161     {
162         OSL_TRACE("LdapUserProfileBackend: access to configuration data failed: %s",
163                 rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
164         return false;
165     }
166 
167     osl::Security aSecurityContext;
168 	if (!aSecurityContext.getUserName(*loggedOnUser))
169 		OSL_TRACE("LdapUserProfileBackend - could not get Logged on user from system");
170 
171     sal_Int32 nIndex = loggedOnUser->indexOf('/');
172 	if (nIndex > 0)
173 		*loggedOnUser = loggedOnUser->copy(nIndex+1);
174 
175     //Remember to remove
176     OSL_TRACE("Logged on user is %s", rtl::OUStringToOString(*loggedOnUser,RTL_TEXTENCODING_ASCII_US).getStr());
177 
178     return true;
179 }
180 
181 //------------------------------------------------------------------------------
182 bool LdapUserProfileBe::getLdapStringParam(
183 	uno::Reference<container::XNameAccess>& xAccess,
184 	const rtl::OUString& aLdapSetting,
185 	rtl::OString& aServerParameter)
186 {
187     rtl::OUString sParam;
188     xAccess->getByName(aLdapSetting) >>= sParam;
189     aServerParameter = rtl::OUStringToOString(sParam, RTL_TEXTENCODING_ASCII_US);
190 
191     return aServerParameter.getLength() != 0;
192 }
193 //------------------------------------------------------------------------------
194 void LdapUserProfileBe::setPropertyValue(
195     rtl::OUString const &, css::uno::Any const &)
196     throw (
197         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
198         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
199         css::uno::RuntimeException)
200 {
201     throw css::lang::IllegalArgumentException(
202         rtl::OUString(
203             RTL_CONSTASCII_USTRINGPARAM("setPropertyValue not supported")),
204         static_cast< cppu::OWeakObject * >(this), -1);
205 }
206 
207 css::uno::Any LdapUserProfileBe::getPropertyValue(
208     rtl::OUString const & PropertyName)
209     throw (
210         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
211         css::uno::RuntimeException)
212 {
213     for (sal_Int32 i = 0;;) {
214         sal_Int32 j = PropertyName.indexOf(',', i);
215         if (j == -1) {
216             j = PropertyName.getLength();
217         }
218         if (j == i) {
219             throw css::beans::UnknownPropertyException(
220                 PropertyName, static_cast< cppu::OWeakObject * >(this));
221         }
222         LdapData::iterator k(data_.find(PropertyName.copy(i, j - i)));
223         if (k != data_.end()) {
224             return css::uno::makeAny(
225                 css::beans::Optional< css::uno::Any >(
226                     true, css::uno::makeAny(k->second)));
227         }
228         if (j == PropertyName.getLength()) {
229             break;
230         }
231         i = j + 1;
232     }
233     return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
234 }
235 
236 //------------------------------------------------------------------------------
237 rtl::OUString SAL_CALL LdapUserProfileBe::getLdapUserProfileBeName(void) {
238 	return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.LdapUserProfileBe") ;
239 }
240 //------------------------------------------------------------------------------
241 
242 rtl::OUString SAL_CALL LdapUserProfileBe::getImplementationName(void)
243     throw (uno::RuntimeException)
244 {
245     return getLdapUserProfileBeName() ;
246 }
247 //------------------------------------------------------------------------------
248 
249 uno::Sequence<rtl::OUString> SAL_CALL LdapUserProfileBe::getLdapUserProfileBeServiceNames(void)
250 {
251     uno::Sequence<rtl::OUString> aServices(1) ;
252     aServices[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.LdapUserProfileBe")) ;
253     return aServices ;
254 }
255 //------------------------------------------------------------------------------
256 
257 sal_Bool SAL_CALL LdapUserProfileBe::supportsService(const rtl::OUString& aServiceName)
258     throw (uno::RuntimeException)
259 {
260     uno::Sequence< rtl::OUString > const svc = getLdapUserProfileBeServiceNames();
261 
262 	for(sal_Int32 i = 0; i < svc.getLength(); ++i )
263 		if(svc[i] == aServiceName)
264 			return true;
265 	return false;
266 }
267 
268 //------------------------------------------------------------------------------
269 
270 uno::Sequence<rtl::OUString>
271 SAL_CALL LdapUserProfileBe::getSupportedServiceNames(void)
272     throw (uno::RuntimeException)
273 {
274     return getLdapUserProfileBeServiceNames() ;
275 }
276 // ---------------------------------------------------------------------------------------
277 }}}
278 // ---------------------------------------------------------------------------------------
279 
280 
281