1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2006-2021 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This program was originally developed by Kurt D. Zeilenga for inclusion
17  * in OpenLDAP Software.
18  */
19 
20 /*
21  * LDAPv3 Transactions (draft-zeilenga-ldap-txn)
22  */
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 #include <ac/stdlib.h>
28 
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/time.h>
32 
33 #include "ldap-int.h"
34 #include "ldap_log.h"
35 
36 int
ldap_txn_start(LDAP * ld,LDAPControl ** sctrls,LDAPControl ** cctrls,int * msgidp)37 ldap_txn_start(
38 	LDAP *ld,
39 	LDAPControl **sctrls,
40 	LDAPControl **cctrls,
41 	int *msgidp )
42 {
43 	return ldap_extended_operation( ld, LDAP_EXOP_TXN_START,
44 		NULL, sctrls, cctrls, msgidp );
45 }
46 
47 int
ldap_txn_start_s(LDAP * ld,LDAPControl ** sctrls,LDAPControl ** cctrls,struct berval ** txnid)48 ldap_txn_start_s(
49 	LDAP *ld,
50 	LDAPControl **sctrls,
51 	LDAPControl **cctrls,
52 	struct berval **txnid )
53 {
54 	assert( txnid != NULL );
55 
56 	return ldap_extended_operation_s( ld, LDAP_EXOP_TXN_START,
57 		NULL, sctrls, cctrls, NULL, txnid );
58 }
59 
60 int
ldap_txn_end(LDAP * ld,int commit,struct berval * txnid,LDAPControl ** sctrls,LDAPControl ** cctrls,int * msgidp)61 ldap_txn_end(
62 	LDAP *ld,
63 	int commit,
64 	struct berval *txnid,
65 	LDAPControl **sctrls,
66 	LDAPControl **cctrls,
67 	int *msgidp )
68 {
69 	int rc;
70 	BerElement *txnber = NULL;
71 	struct berval *txnval = NULL;
72 
73 	assert( txnid != NULL );
74 
75 	txnber = ber_alloc_t( LBER_USE_DER );
76 
77 	if( commit ) {
78 		ber_printf( txnber, "{ON}", txnid );
79 	} else {
80 		ber_printf( txnber, "{bON}", commit, txnid );
81 	}
82 
83 	ber_flatten( txnber, &txnval );
84 
85 	rc = ldap_extended_operation( ld, LDAP_EXOP_TXN_END,
86 		txnval, sctrls, cctrls, msgidp );
87 
88 	ber_free( txnber, 1 );
89 	return rc;
90 }
91 
92 int
ldap_txn_end_s(LDAP * ld,int commit,struct berval * txnid,LDAPControl ** sctrls,LDAPControl ** cctrls,int * retidp)93 ldap_txn_end_s(
94 	LDAP *ld,
95 	int commit,
96 	struct berval *txnid,
97 	LDAPControl **sctrls,
98 	LDAPControl **cctrls,
99 	int *retidp )
100 {
101 	int rc;
102 	BerElement *txnber = NULL;
103 	struct berval *txnval = NULL;
104 	struct berval *retdata = NULL;
105 
106 	if ( retidp != NULL ) *retidp = -1;
107 
108 	txnber = ber_alloc_t( LBER_USE_DER );
109 
110 	if( commit ) {
111 		ber_printf( txnber, "{ON}", txnid );
112 	} else {
113 		ber_printf( txnber, "{bON}", commit, txnid );
114 	}
115 
116 	ber_flatten( txnber, &txnval );
117 
118 	rc = ldap_extended_operation_s( ld, LDAP_EXOP_TXN_END,
119 		txnval, sctrls, cctrls, NULL, &retdata );
120 
121 	ber_free( txnber, 1 );
122 
123 	/* parse retdata */
124 	if( retdata != NULL ) {
125 		BerElement *ber;
126 		ber_tag_t tag;
127 		ber_int_t retid;
128 
129 		if( retidp == NULL ) goto done;
130 
131 		ber = ber_init( retdata );
132 
133 		if( ber == NULL ) {
134 			rc = ld->ld_errno = LDAP_NO_MEMORY;
135 			goto done;
136 		}
137 
138 		tag = ber_scanf( ber, "i", &retid );
139 		ber_free( ber, 1 );
140 
141 		if ( tag != LBER_INTEGER ) {
142 			rc = ld->ld_errno = LDAP_DECODING_ERROR;
143 			goto done;
144 		}
145 
146 		*retidp = (int) retid;
147 
148 done:
149 		ber_bvfree( retdata );
150 	}
151 
152 	return rc;
153 }
154