or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdcontrols-extensions.mdcore-operations.mddata-types.mdindex.mdldif.mdpersistence.mdschema.mdsearch.md

controls-extensions.mddocs/

0

# Controls and Extensions

1

2

Standard LDAP controls and extended operations for advanced directory functionality including paged results, server-side sorting, persistent search, and password management.

3

4

## Capabilities

5

6

### Standard LDAP Controls

7

8

#### Paged Results Controls

9

10

```java { .api }

11

/**

12

* Control for retrieving search results in pages

13

*/

14

public class PagedResultsRequestControl extends Control {

15

public PagedResultsRequestControl(int pageSize);

16

public PagedResultsRequestControl(int pageSize, ASN1OctetString cookie);

17

18

public int getSize();

19

public ASN1OctetString getCookie();

20

}

21

22

/**

23

* Response control for paged results

24

*/

25

public class SimplePagedResultsControl extends Control {

26

public int getSize();

27

public ASN1OctetString getCookie();

28

public boolean moreResultsToReturn();

29

30

public static SimplePagedResultsControl get(LDAPResult result);

31

}

32

```

33

34

#### Server-Side Sort Controls

35

36

```java { .api }

37

/**

38

* Control for server-side sorting of search results

39

*/

40

public class ServerSideSortRequestControl extends Control {

41

public ServerSideSortRequestControl(SortKey... sortKeys);

42

public ServerSideSortRequestControl(List<SortKey> sortKeys);

43

44

public List<SortKey> getSortKeys();

45

}

46

47

/**

48

* Sort key specification

49

*/

50

public class SortKey implements Serializable {

51

public SortKey(String attributeName);

52

public SortKey(String attributeName, boolean reverseOrder);

53

public SortKey(String attributeName, String matchingRuleID, boolean reverseOrder);

54

55

public String getAttributeName();

56

public String getMatchingRuleID();

57

public boolean reverseOrder();

58

}

59

60

/**

61

* Response control for server-side sort status

62

*/

63

public class ServerSideSortResponseControl extends Control {

64

public ResultCode getResultCode();

65

public String getAttributeName();

66

}

67

```

68

69

#### Authorization Controls

70

71

```java { .api }

72

/**

73

* Control for proxied authorization (version 1)

74

*/

75

public class ProxiedAuthorizationV1RequestControl extends Control {

76

public ProxiedAuthorizationV1RequestControl(String proxyDN);

77

78

public String getProxyDN();

79

}

80

81

/**

82

* Control for proxied authorization (version 2)

83

*/

84

public class ProxiedAuthorizationV2RequestControl extends Control {

85

public ProxiedAuthorizationV2RequestControl(String authorizationID);

86

87

public String getAuthorizationID();

88

}

89

90

/**

91

* Control for requesting authorization identity

92

*/

93

public class AuthorizationIdentityRequestControl extends Control {

94

public AuthorizationIdentityRequestControl();

95

}

96

97

/**

98

* Response control containing authorization identity

99

*/

100

public class AuthorizationIdentityResponseControl extends Control {

101

public String getAuthorizationID();

102

}

103

```

104

105

### Extended Operations

106

107

#### Password Management

108

109

```java { .api }

110

/**

111

* Extended operation for password modification

112

*/

113

public class PasswordModifyExtendedRequest extends ExtendedRequest {

114

public PasswordModifyExtendedRequest();

115

public PasswordModifyExtendedRequest(String userIdentity, String oldPassword, String newPassword);

116

117

public String getUserIdentity();

118

public String getOldPassword();

119

public String getNewPassword();

120

}

121

122

/**

123

* Result for password modify operation

124

*/

125

public class PasswordModifyExtendedResult extends ExtendedResult {

126

public String getGeneratedPassword();

127

}

128

```

129

130

#### Identity Operations

131

132

```java { .api }

133

/**

134

* Extended operation to determine current identity

135

*/

136

public class WhoAmIExtendedRequest extends ExtendedRequest {

137

public WhoAmIExtendedRequest();

138

}

139

140

/**

141

* Result containing current authorization identity

142

*/

143

public class WhoAmIExtendedResult extends ExtendedResult {

144

public String getAuthorizationID();

145

}

146

```

147

148

#### Transaction Support

149

150

```java { .api }

151

/**

152

* Extended operation to start a transaction

153

*/

154

public class StartTransactionExtendedRequest extends ExtendedRequest {

155

public StartTransactionExtendedRequest();

156

}

157

158

/**

159

* Result for start transaction operation

160

*/

161

public class StartTransactionExtendedResult extends ExtendedResult {

162

public ASN1OctetString getTransactionID();

163

}

164

165

/**

166

* Extended operation to end a transaction

167

*/

168

public class EndTransactionExtendedRequest extends ExtendedRequest {

169

public EndTransactionExtendedRequest(ASN1OctetString transactionID, boolean commit);

170

171

public ASN1OctetString getTransactionID();

172

public boolean commit();

173

}

174

```

175

176

#### SSL/TLS Support

177

178

```java { .api }

179

/**

180

* Extended operation to start TLS encryption

181

*/

182

public class StartTLSExtendedRequest extends ExtendedRequest {

183

public StartTLSExtendedRequest();

184

public StartTLSExtendedRequest(SSLContext sslContext);

185

public StartTLSExtendedRequest(SSLSocketFactory socketFactory);

186

}

187

```

188

189

## Usage Examples

190

191

### Paged Search Results

192

193

```java

194

import com.unboundid.ldap.sdk.*;

195

import com.unboundid.ldap.sdk.controls.*;

196

197

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

198

199

try {

200

connection.bind("cn=admin,dc=example,dc=com", "password");

201

202

SearchRequest searchRequest = new SearchRequest(

203

"dc=example,dc=com",

204

SearchScope.SUB,

205

"(objectClass=inetOrgPerson)",

206

"cn", "mail"

207

);

208

209

int pageSize = 10;

210

ASN1OctetString cookie = null;

211

212

do {

213

searchRequest.setControls(new PagedResultsRequestControl(pageSize, cookie));

214

SearchResult result = connection.search(searchRequest);

215

216

System.out.println("Page with " + result.getEntryCount() + " entries:");

217

for (SearchResultEntry entry : result.getSearchEntries()) {

218

System.out.println(" " + entry.getAttributeValue("cn"));

219

}

220

221

SimplePagedResultsControl responseControl =

222

SimplePagedResultsControl.get(result);

223

cookie = (responseControl != null) ? responseControl.getCookie() : null;

224

225

} while ((cookie != null) && (cookie.getValueLength() > 0));

226

227

} finally {

228

connection.close();

229

}

230

```

231

232

### Server-Side Sorting

233

234

```java

235

import com.unboundid.ldap.sdk.*;

236

import com.unboundid.ldap.sdk.controls.*;

237

238

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

239

240

try {

241

connection.bind("cn=admin,dc=example,dc=com", "password");

242

243

SearchRequest searchRequest = new SearchRequest(

244

"dc=example,dc=com",

245

SearchScope.SUB,

246

"(objectClass=inetOrgPerson)",

247

"cn", "sn", "mail", "department"

248

);

249

250

// Sort by department, then by surname

251

SortKey[] sortKeys = {

252

new SortKey("department"),

253

new SortKey("sn")

254

};

255

256

searchRequest.addControl(new ServerSideSortRequestControl(sortKeys));

257

258

SearchResult result = connection.search(searchRequest);

259

260

// Check if sorting was successful

261

ServerSideSortResponseControl sortResponse =

262

result.getResponseControl(ServerSideSortResponseControl.class);

263

264

if (sortResponse != null && sortResponse.getResultCode() == ResultCode.SUCCESS) {

265

System.out.println("Results sorted successfully");

266

}

267

268

// Results are now sorted by department, then surname

269

for (SearchResultEntry entry : result.getSearchEntries()) {

270

System.out.println(entry.getAttributeValue("department") +

271

" - " + entry.getAttributeValue("sn") +

272

", " + entry.getAttributeValue("cn"));

273

}

274

275

} finally {

276

connection.close();

277

}

278

```

279

280

### Password Modification

281

282

```java

283

import com.unboundid.ldap.sdk.*;

284

import com.unboundid.ldap.sdk.extensions.*;

285

286

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

287

288

try {

289

connection.bind("cn=admin,dc=example,dc=com", "password");

290

291

// Change password for specific user

292

PasswordModifyExtendedRequest passwordRequest = new PasswordModifyExtendedRequest(

293

"cn=john.doe,ou=people,dc=example,dc=com", // user identity

294

"oldPassword", // old password

295

"newSecurePassword123" // new password

296

);

297

298

PasswordModifyExtendedResult passwordResult =

299

(PasswordModifyExtendedResult) connection.processExtendedOperation(passwordRequest);

300

301

if (passwordResult.getResultCode() == ResultCode.SUCCESS) {

302

System.out.println("Password changed successfully");

303

} else {

304

System.err.println("Password change failed: " + passwordResult.getDiagnosticMessage());

305

}

306

307

// Generate new password (let server generate)

308

PasswordModifyExtendedRequest generateRequest = new PasswordModifyExtendedRequest(

309

"cn=jane.smith,ou=people,dc=example,dc=com",

310

"currentPassword",

311

null // null = let server generate new password

312

);

313

314

PasswordModifyExtendedResult generateResult =

315

(PasswordModifyExtendedResult) connection.processExtendedOperation(generateRequest);

316

317

if (generateResult.getResultCode() == ResultCode.SUCCESS) {

318

System.out.println("Generated password: " + generateResult.getGeneratedPassword());

319

}

320

321

} finally {

322

connection.close();

323

}

324

```

325

326

### Authorization Identity

327

328

```java

329

import com.unboundid.ldap.sdk.*;

330

import com.unboundid.ldap.sdk.extensions.*;

331

import com.unboundid.ldap.sdk.controls.*;

332

333

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

334

335

try {

336

connection.bind("cn=admin,dc=example,dc=com", "password");

337

338

// Determine current authorization identity

339

WhoAmIExtendedRequest whoAmIRequest = new WhoAmIExtendedRequest();

340

WhoAmIExtendedResult whoAmIResult =

341

(WhoAmIExtendedResult) connection.processExtendedOperation(whoAmIRequest);

342

343

if (whoAmIResult.getResultCode() == ResultCode.SUCCESS) {

344

System.out.println("Current identity: " + whoAmIResult.getAuthorizationID());

345

}

346

347

// Perform operation with proxied authorization

348

SearchRequest searchRequest = new SearchRequest(

349

"dc=example,dc=com",

350

SearchScope.ONE,

351

"(objectClass=*)",

352

"1.1" // no attributes, just check access

353

);

354

355

// Act as different user

356

searchRequest.addControl(new ProxiedAuthorizationV2RequestControl(

357

"dn:cn=readonly,ou=service,dc=example,dc=com"

358

));

359

360

// Request authorization identity in response

361

searchRequest.addControl(new AuthorizationIdentityRequestControl());

362

363

SearchResult result = connection.search(searchRequest);

364

365

// Check what identity was actually used

366

AuthorizationIdentityResponseControl authzResponse =

367

result.getResponseControl(AuthorizationIdentityResponseControl.class);

368

369

if (authzResponse != null) {

370

System.out.println("Operation performed as: " + authzResponse.getAuthorizationID());

371

}

372

373

} finally {

374

connection.close();

375

}

376

```

377

378

### Transaction Operations

379

380

```java

381

import com.unboundid.ldap.sdk.*;

382

import com.unboundid.ldap.sdk.extensions.*;

383

import com.unboundid.ldap.sdk.controls.*;

384

385

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

386

387

try {

388

connection.bind("cn=admin,dc=example,dc=com", "password");

389

390

// Start transaction

391

StartTransactionExtendedRequest startTxnRequest = new StartTransactionExtendedRequest();

392

StartTransactionExtendedResult startTxnResult =

393

(StartTransactionExtendedResult) connection.processExtendedOperation(startTxnRequest);

394

395

if (startTxnResult.getResultCode() != ResultCode.SUCCESS) {

396

throw new LDAPException(startTxnResult.getResultCode(), "Failed to start transaction");

397

}

398

399

ASN1OctetString transactionID = startTxnResult.getTransactionID();

400

System.out.println("Transaction started");

401

402

try {

403

// Create transaction control

404

TransactionSpecificationRequestControl txnControl =

405

new TransactionSpecificationRequestControl(transactionID);

406

407

// Perform operations within transaction

408

AddRequest addRequest1 = new AddRequest(

409

"cn=user1,ou=people,dc=example,dc=com",

410

new Attribute("objectClass", "inetOrgPerson"),

411

new Attribute("cn", "user1"),

412

new Attribute("sn", "User")

413

);

414

addRequest1.addControl(txnControl);

415

416

AddRequest addRequest2 = new AddRequest(

417

"cn=user2,ou=people,dc=example,dc=com",

418

new Attribute("objectClass", "inetOrgPerson"),

419

new Attribute("cn", "user2"),

420

new Attribute("sn", "User")

421

);

422

addRequest2.addControl(txnControl);

423

424

// Execute operations (won't be committed until transaction ends)

425

connection.add(addRequest1);

426

connection.add(addRequest2);

427

428

System.out.println("Operations queued in transaction");

429

430

// Commit transaction

431

EndTransactionExtendedRequest commitRequest =

432

new EndTransactionExtendedRequest(transactionID, true);

433

434

ExtendedResult commitResult = connection.processExtendedOperation(commitRequest);

435

436

if (commitResult.getResultCode() == ResultCode.SUCCESS) {

437

System.out.println("Transaction committed successfully");

438

} else {

439

System.err.println("Transaction commit failed: " + commitResult.getDiagnosticMessage());

440

}

441

442

} catch (LDAPException e) {

443

// Rollback transaction on error

444

System.err.println("Error in transaction: " + e.getMessage());

445

446

EndTransactionExtendedRequest rollbackRequest =

447

new EndTransactionExtendedRequest(transactionID, false);

448

449

connection.processExtendedOperation(rollbackRequest);

450

System.out.println("Transaction rolled back");

451

}

452

453

} finally {

454

connection.close();

455

}

456

```

457

458

### Start TLS

459

460

```java

461

import com.unboundid.ldap.sdk.*;

462

import com.unboundid.ldap.sdk.extensions.*;

463

import com.unboundid.util.ssl.*;

464

465

// Start with plain connection

466

LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);

467

468

try {

469

// Create SSL context

470

SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager());

471

472

// Start TLS to upgrade connection to SSL

473

StartTLSExtendedRequest startTLSRequest =

474

new StartTLSExtendedRequest(sslUtil.createSSLContext());

475

476

ExtendedResult startTLSResult = connection.processExtendedOperation(startTLSRequest);

477

478

if (startTLSResult.getResultCode() == ResultCode.SUCCESS) {

479

System.out.println("TLS started successfully");

480

System.out.println("Connection is now encrypted");

481

482

// Now authenticate over the encrypted connection

483

connection.bind("cn=admin,dc=example,dc=com", "password");

484

485

// Perform operations over encrypted connection

486

SearchResult result = connection.search("dc=example,dc=com", SearchScope.BASE, "(objectClass=*)");

487

System.out.println("Secure search completed");

488

489

} else {

490

System.err.println("Start TLS failed: " + startTLSResult.getDiagnosticMessage());

491

}

492

493

} catch (Exception e) {

494

System.err.println("TLS operation failed: " + e.getMessage());

495

} finally {

496

connection.close();

497

}

498

```