1 /*
2  * string.c - ssh string functions
3  *
4  * This file is part of the SSH Library
5  *
6  * Copyright (c) 2003-2008 by Aris Adamantiadis
7  *
8  * The SSH Library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or (at your
11  * option) any later version.
12  *
13  * The SSH Library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with the SSH Library; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21  * MA 02111-1307, USA.
22  */
23 
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #ifndef _WIN32
29 #include <arpa/inet.h>
30 #endif
31 
32 #include "libssh/priv.h"
33 #include "libssh/string.h"
34 
35 /**
36  * @defgroup libssh_string The SSH string functions
37  * @ingroup libssh
38  *
39  * @brief String manipulations used in libssh.
40  *
41  * @{
42  */
43 
44 /**
45  * @brief Create a new SSH String object.
46  *
47  * @param[in] size       The size of the string.
48  *
49  * @return               The newly allocated string, NULL on error.
50  */
ssh_string_new(size_t size)51 struct ssh_string_struct *ssh_string_new(size_t size) {
52   struct ssh_string_struct *str = NULL;
53 
54   str = malloc(sizeof(struct ssh_string_struct) + size);
55   if (str == NULL) {
56     return NULL;
57   }
58 
59   str->size = htonl(size);
60   str->data[0] = 0;
61 
62   return str;
63 }
64 
65 /**
66  * @brief Fill a string with given data. The string should be big enough.
67  *
68  * @param s        An allocated string to fill with data.
69  *
70  * @param data     The data to fill the string with.
71  *
72  * @param len      Size of data.
73  *
74  * @return         0 on success, < 0 on error.
75  */
ssh_string_fill(struct ssh_string_struct * s,const void * data,size_t len)76 int ssh_string_fill(struct ssh_string_struct *s, const void *data, size_t len) {
77   if ((s == NULL) || (data == NULL) ||
78       (len == 0) || (len > ssh_string_len(s))) {
79     return -1;
80   }
81 
82   memcpy(s->data, data, len);
83 
84   return 0;
85 }
86 
87 /**
88  * @brief Create a ssh string using a C string
89  *
90  * @param[in] what      The source 0-terminated C string.
91  *
92  * @return              The newly allocated string, NULL on error with errno
93  *                      set.
94  *
95  * @note The nul byte is not copied nor counted in the ouput string.
96  */
ssh_string_from_char(const char * what)97 struct ssh_string_struct *ssh_string_from_char(const char *what) {
98   struct ssh_string_struct *ptr;
99   size_t len;
100 
101   if(what == NULL) {
102       errno = EINVAL;
103       return NULL;
104   }
105 
106   len = strlen(what);
107 
108   ptr = ssh_string_new(len);
109   if (ptr == NULL) {
110     return NULL;
111   }
112 
113   memcpy(ptr->data, what, len);
114 
115   return ptr;
116 }
117 
118 /**
119  * @brief Return the size of a SSH string.
120  *
121  * @param[in] s         The the input SSH string.
122  *
123  * @return The size of the content of the string, 0 on error.
124  */
ssh_string_len(struct ssh_string_struct * s)125 size_t ssh_string_len(struct ssh_string_struct *s) {
126   if (s == NULL) {
127     return ntohl(0);
128   }
129 
130   return ntohl(s->size);
131 }
132 
133 /**
134  * @brief Get the the string as a C nul-terminated string.
135  *
136  * This is only available as long as the SSH string exists.
137  *
138  * @param[in] s         The SSH string to get the C string from.
139  *
140  * @return              The char pointer, NULL on error.
141  */
ssh_string_get_char(struct ssh_string_struct * s)142 const char *ssh_string_get_char(struct ssh_string_struct *s)
143 {
144     if (s == NULL) {
145         return NULL;
146     }
147     s->data[ssh_string_len(s)] = '\0';
148 
149     return (const char *) s->data;
150 }
151 
152 /**
153  * @brief Convert a SSH string to a C nul-terminated string.
154  *
155  * @param[in] s         The SSH input string.
156  *
157  * @return              An allocated string pointer, NULL on error with errno
158  *                      set.
159  *
160  * @note If the input SSH string contains zeroes, some parts of the output
161  * string may not be readable with regular libc functions.
162  */
ssh_string_to_char(struct ssh_string_struct * s)163 char *ssh_string_to_char(struct ssh_string_struct *s) {
164 	size_t len;
165 	char *new;
166     if (s == NULL || s->data == NULL)
167 		return NULL;
168   len = ssh_string_len(s) + 1;
169   new = malloc(len);
170 
171   if (new == NULL) {
172     return NULL;
173   }
174   memcpy(new, s->data, len - 1);
175   new[len - 1] = '\0';
176   return new;
177 }
178 
179 /**
180  * @brief Deallocate a char string object.
181  *
182  * @param[in] s         The string to delete.
183  */
ssh_string_free_char(char * s)184 void ssh_string_free_char(char *s) {
185     SAFE_FREE(s);
186 }
187 
188 /**
189  * @brief Copy a string, return a newly allocated string. The caller has to
190  *        free the string.
191  *
192  * @param[in] s         String to copy.
193  *
194  * @return              Newly allocated copy of the string, NULL on error.
195  */
ssh_string_copy(struct ssh_string_struct * s)196 struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) {
197   struct ssh_string_struct *new;
198 
199   if (s == NULL || s->data == NULL) {
200       return NULL;
201   }
202 
203   new = ssh_string_new(ssh_string_len(s));
204   if (new == NULL) {
205     return NULL;
206   }
207 
208   memcpy(new->data, s->data, ssh_string_len(s));
209 
210   return new;
211 }
212 
213 /**
214  * @brief Destroy the data in a string so it couldn't appear in a core dump.
215  *
216  * @param[in] s         The string to burn.
217  */
ssh_string_burn(struct ssh_string_struct * s)218 void ssh_string_burn(struct ssh_string_struct *s) {
219   if (s == NULL) {
220     return;
221   }
222   memset(s->data, 'X', ssh_string_len(s));
223 }
224 
225 /**
226  * @brief Get the payload of the string.
227  *
228  * @param s             The string to get the data from.
229  *
230  * @return              Return the data of the string or NULL on error.
231  */
ssh_string_data(struct ssh_string_struct * s)232 void *ssh_string_data(struct ssh_string_struct *s) {
233   if (s == NULL) {
234     return NULL;
235   }
236 
237   return s->data;
238 }
239 
240 /**
241  * @brief Deallocate a SSH string object.
242  *
243  * \param[in] s         The SSH string to delete.
244  */
ssh_string_free(struct ssh_string_struct * s)245 void ssh_string_free(struct ssh_string_struct *s) {
246   SAFE_FREE(s);
247 }
248 
249 /** @} */
250 
251 /* vim: set ts=4 sw=4 et cindent: */
252