1/* $NetBSD: getattr.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */ 2 3/* $OpenLDAP$ */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2021 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17/* Portions Copyright (c) 1990 Regents of the University of Michigan. 18 * All rights reserved. 19 */ 20 21#include <sys/cdefs.h> 22__RCSID("$NetBSD: getattr.c,v 1.3 2021/08/14 16:14:56 christos Exp $"); 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 35char * 36ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berout ) 37{ 38 int rc; 39 ber_tag_t tag; 40 ber_len_t len = 0; 41 char *attr; 42 BerElement *ber; 43 44 Debug0( LDAP_DEBUG_TRACE, "ldap_first_attribute\n" ); 45 46 assert( ld != NULL ); 47 assert( LDAP_VALID( ld ) ); 48 assert( entry != NULL ); 49 assert( berout != NULL ); 50 51 *berout = NULL; 52 53 ber = ldap_alloc_ber_with_options( ld ); 54 if( ber == NULL ) { 55 return NULL; 56 } 57 58 *ber = *entry->lm_ber; 59 60 /* 61 * Skip past the sequence, dn, sequence of sequence leaving 62 * us at the first attribute. 63 */ 64 65 tag = ber_scanf( ber, "{xl{" /*}}*/, &len ); 66 if( tag == LBER_ERROR ) { 67 ld->ld_errno = LDAP_DECODING_ERROR; 68 ber_free( ber, 0 ); 69 return NULL; 70 } 71 72 /* set the length to avoid overrun */ 73 rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); 74 if( rc != LBER_OPT_SUCCESS ) { 75 ld->ld_errno = LDAP_LOCAL_ERROR; 76 ber_free( ber, 0 ); 77 return NULL; 78 } 79 80 if ( ber_pvt_ber_remaining( ber ) == 0 ) { 81 assert( len == 0 ); 82 ber_free( ber, 0 ); 83 return NULL; 84 } 85 assert( len != 0 ); 86 87 /* snatch the first attribute */ 88 tag = ber_scanf( ber, "{ax}", &attr ); 89 if( tag == LBER_ERROR ) { 90 ld->ld_errno = LDAP_DECODING_ERROR; 91 ber_free( ber, 0 ); 92 return NULL; 93 } 94 95 *berout = ber; 96 return attr; 97} 98 99/* ARGSUSED */ 100char * 101ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber ) 102{ 103 ber_tag_t tag; 104 char *attr; 105 106 Debug0( LDAP_DEBUG_TRACE, "ldap_next_attribute\n" ); 107 108 assert( ld != NULL ); 109 assert( LDAP_VALID( ld ) ); 110 assert( entry != NULL ); 111 assert( ber != NULL ); 112 113 if ( ber_pvt_ber_remaining( ber ) == 0 ) { 114 return NULL; 115 } 116 117 /* skip sequence, snarf attribute type, skip values */ 118 tag = ber_scanf( ber, "{ax}", &attr ); 119 if( tag == LBER_ERROR ) { 120 ld->ld_errno = LDAP_DECODING_ERROR; 121 return NULL; 122 } 123 124 return attr; 125} 126 127/* Fetch attribute type and optionally fetch values. The type 128 * and values are referenced in-place from the BerElement, they are 129 * not dup'd into malloc'd memory. 130 */ 131/* ARGSUSED */ 132int 133ldap_get_attribute_ber( LDAP *ld, LDAPMessage *entry, BerElement *ber, 134 BerValue *attr, BerVarray *vals ) 135{ 136 ber_tag_t tag; 137 int rc = LDAP_SUCCESS; 138 139 Debug0( LDAP_DEBUG_TRACE, "ldap_get_attribute_ber\n" ); 140 141 assert( ld != NULL ); 142 assert( LDAP_VALID( ld ) ); 143 assert( entry != NULL ); 144 assert( ber != NULL ); 145 assert( attr != NULL ); 146 147 attr->bv_val = NULL; 148 attr->bv_len = 0; 149 150 if ( ber_pvt_ber_remaining( ber ) ) { 151 ber_len_t siz = sizeof( BerValue ); 152 153 /* skip sequence, snarf attribute type */ 154 tag = ber_scanf( ber, vals ? "{mM}" : "{mx}", attr, vals, 155 &siz, (ber_len_t)0 ); 156 if( tag == LBER_ERROR ) { 157 rc = ld->ld_errno = LDAP_DECODING_ERROR; 158 } 159 } 160 161 return rc; 162} 163