~ubuntu-branches/ubuntu/oneiric/mcollective/oneiric-proposed

« back to all changes in this revision

Viewing changes to doc/classes/MCollective/Security/Aes_security.html

  • Committer: Bazaar Package Importer
  • Author(s): Marc Cluet, Marc Cluet, Chuck Short
  • Date: 2011-05-05 07:37:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110505073754-klk1jkz8afi4fomx
Tags: 1.2.0-0ubuntu1
[Marc Cluet]
* Update to 1.2.0
* Build for Oneiric.

[Chuck Short]
* Drop ruby from mcollective, mcollective-middleware, mcollective-client
  since its a dependency of mcollective-common.
* Bump standards to 3.9.2.
* Fix up lintian warnings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="iso-8859-1"?>
 
2
<!DOCTYPE html 
 
3
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 
4
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
5
 
 
6
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
7
<head>
 
8
  <title>Class: MCollective::Security::Aes_security</title>
 
9
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 
10
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
 
11
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
 
12
  <script type="text/javascript">
 
13
  // <![CDATA[
 
14
 
 
15
  function popupCode( url ) {
 
16
    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
 
17
  }
 
18
 
 
19
  function toggleCode( id ) {
 
20
    if ( document.getElementById )
 
21
      elem = document.getElementById( id );
 
22
    else if ( document.all )
 
23
      elem = eval( "document.all." + id );
 
24
    else
 
25
      return false;
 
26
 
 
27
    elemStyle = elem.style;
 
28
    
 
29
    if ( elemStyle.display != "block" ) {
 
30
      elemStyle.display = "block"
 
31
    } else {
 
32
      elemStyle.display = "none"
 
33
    }
 
34
 
 
35
    return true;
 
36
  }
 
37
  
 
38
  // Make codeblocks hidden by default
 
39
  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
 
40
  
 
41
  // ]]>
 
42
  </script>
 
43
 
 
44
</head>
 
45
<body>
 
46
 
 
47
 
 
48
 
 
49
    <div id="classHeader">
 
50
        <table class="header-table">
 
51
        <tr class="top-aligned-row">
 
52
          <td><strong>Class</strong></td>
 
53
          <td class="class-name-in-header">MCollective::Security::Aes_security</td>
 
54
        </tr>
 
55
        <tr class="top-aligned-row">
 
56
            <td><strong>In:</strong></td>
 
57
            <td>
 
58
                <a href="../../../files/plugins/mcollective/security/aes_security_rb.html">
 
59
                plugins/mcollective/security/aes_security.rb
 
60
                </a>
 
61
        <br />
 
62
            </td>
 
63
        </tr>
 
64
 
 
65
        <tr class="top-aligned-row">
 
66
            <td><strong>Parent:</strong></td>
 
67
            <td>
 
68
                <a href="Base.html">
 
69
                Base
 
70
               </a>
 
71
            </td>
 
72
        </tr>
 
73
        </table>
 
74
    </div>
 
75
  <!-- banner header -->
 
76
 
 
77
  <div id="bodyContent">
 
78
 
 
79
 
 
80
 
 
81
  <div id="contextContent">
 
82
 
 
83
    <div id="description">
 
84
      <p>
 
85
Impliments a security system that encrypts payloads using AES and secures
 
86
the AES encrypted data using RSA public/private key encryption.
 
87
</p>
 
88
<p>
 
89
The design goals of this plugin are:
 
90
</p>
 
91
<ul>
 
92
<li>Each actor - clients and servers - can have their own set of public and
 
93
private keys
 
94
 
 
95
</li>
 
96
<li>All actors are uniquely and cryptographically identified
 
97
 
 
98
</li>
 
99
<li>Requests are encrypted using the clients private key and anyone that has
 
100
the public key can see the request. Thus an atacker may see the requests
 
101
given access to network or machine due to the broadcast nature of
 
102
mcollective
 
103
 
 
104
</li>
 
105
<li>Replies are encrypted using the calling clients public key. Thus no-one but
 
106
the caller can view the contents of replies.
 
107
 
 
108
</li>
 
109
<li>Servers can all have their own RSA keys, or share one, or reuse keys
 
110
created by other PKI using software like Puppet
 
111
 
 
112
</li>
 
113
<li>Requests from servers - like registration data - can be secured even to
 
114
external eaves droppers depending on the level of configuration you are
 
115
prepared to do
 
116
 
 
117
</li>
 
118
<li>Given a network where you can ensure third parties are not able to access
 
119
the middleware public key distribution can happen automatically
 
120
 
 
121
</li>
 
122
</ul>
 
123
<p>
 
124
Configuration Options:
 
125
</p>
 
126
<h6>================</h6>
 
127
<p>
 
128
Common Options:
 
129
</p>
 
130
<pre>
 
131
   # Enable this plugin
 
132
   securityprovider = aes_security
 
133
 
 
134
   # Use YAML as serializer
 
135
   plugin.aes.serializer = yaml
 
136
 
 
137
   # Send our public key with every request so servers can learn it
 
138
   plugin.aes.send_pubkey = 1
 
139
</pre>
 
140
<p>
 
141
Clients:
 
142
</p>
 
143
<pre>
 
144
   # The clients public and private keys
 
145
   plugin.aes.client_private = /home/user/.mcollective.d/user-private.pem
 
146
   plugin.aes.client_public = /home/user/.mcollective.d/user.pem
 
147
</pre>
 
148
<p>
 
149
Servers:
 
150
</p>
 
151
<pre>
 
152
   # Where to cache client keys or find manually distributed ones
 
153
   plugin.aes.client_cert_dir = /etc/mcollective/ssl/clients
 
154
 
 
155
   # Cache public keys promiscuously from the network
 
156
   plugin.aes.learn_pubkeys = 1
 
157
 
 
158
   # The servers public and private keys
 
159
   plugin.aes.server_private = /etc/mcollective/ssl/server-private.pem
 
160
   plugin.aes.server_public = /etc/mcollective/ssl/server-public.pem
 
161
</pre>
 
162
 
 
163
    </div>
 
164
 
 
165
 
 
166
   </div>
 
167
 
 
168
    <div id="method-list">
 
169
      <h3 class="section-bar">Methods</h3>
 
170
 
 
171
      <div class="name-list">
 
172
      <a href="#M000015">callerid</a>&nbsp;&nbsp;
 
173
      <a href="#M000024">certname_from_callerid</a>&nbsp;&nbsp;
 
174
      <a href="#M000023">client_cert_dir</a>&nbsp;&nbsp;
 
175
      <a href="#M000019">client_private_key</a>&nbsp;&nbsp;
 
176
      <a href="#M000020">client_public_key</a>&nbsp;&nbsp;
 
177
      <a href="#M000010">decodemsg</a>&nbsp;&nbsp;
 
178
      <a href="#M000017">decrypt</a>&nbsp;&nbsp;
 
179
      <a href="#M000014">deserialize</a>&nbsp;&nbsp;
 
180
      <a href="#M000011">encodereply</a>&nbsp;&nbsp;
 
181
      <a href="#M000012">encoderequest</a>&nbsp;&nbsp;
 
182
      <a href="#M000016">encrypt</a>&nbsp;&nbsp;
 
183
      <a href="#M000018">public_key_path_for_client</a>&nbsp;&nbsp;
 
184
      <a href="#M000013">serialize</a>&nbsp;&nbsp;
 
185
      <a href="#M000022">server_private_key</a>&nbsp;&nbsp;
 
186
      <a href="#M000021">server_public_key</a>&nbsp;&nbsp;
 
187
      </div>
 
188
    </div>
 
189
 
 
190
  </div>
 
191
 
 
192
 
 
193
    <!-- if includes -->
 
194
 
 
195
    <div id="section">
 
196
 
 
197
 
 
198
 
 
199
 
 
200
 
 
201
      
 
202
 
 
203
 
 
204
    <!-- if method_list -->
 
205
    <div id="methods">
 
206
      <h3 class="section-bar">Public Instance methods</h3>
 
207
 
 
208
      <div id="method-M000015" class="method-detail">
 
209
        <a name="M000015"></a>
 
210
 
 
211
        <div class="method-heading">
 
212
          <a href="#M000015" class="method-signature">
 
213
          <span class="method-name">callerid</span><span class="method-args">()</span>
 
214
          </a>
 
215
        </div>
 
216
      
 
217
        <div class="method-description">
 
218
          <p>
 
219
sets the caller id to the md5 of the public key
 
220
</p>
 
221
          <p><a class="source-toggle" href="#"
 
222
            onclick="toggleCode('M000015-source');return false;">[Source]</a></p>
 
223
          <div class="method-source-code" id="M000015-source">
 
224
<pre>
 
225
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 151</span>
 
226
151:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">callerid</span>
 
227
152:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@initiated_by</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:client</span>
 
228
153:                     <span class="ruby-keyword kw">return</span> <span class="ruby-node">&quot;cert=#{File.basename(client_public_key).gsub(/\.pem$/, '')}&quot;</span>
 
229
154:                 <span class="ruby-keyword kw">else</span>
 
230
155:                     <span class="ruby-comment cmt"># servers need to set callerid as well, not usually needed but</span>
 
231
156:                     <span class="ruby-comment cmt"># would be if you're doing registration or auditing or generating</span>
 
232
157:                     <span class="ruby-comment cmt"># requests for some or other reason</span>
 
233
158:                     <span class="ruby-keyword kw">return</span> <span class="ruby-node">&quot;cert=#{File.basename(server_public_key).gsub(/\.pem$/, '')}&quot;</span>
 
234
159:                 <span class="ruby-keyword kw">end</span>
 
235
160:             <span class="ruby-keyword kw">end</span>
 
236
</pre>
 
237
          </div>
 
238
        </div>
 
239
      </div>
 
240
 
 
241
      <div id="method-M000024" class="method-detail">
 
242
        <a name="M000024"></a>
 
243
 
 
244
        <div class="method-heading">
 
245
          <a href="#M000024" class="method-signature">
 
246
          <span class="method-name">certname_from_callerid</span><span class="method-args">(id)</span>
 
247
          </a>
 
248
        </div>
 
249
      
 
250
        <div class="method-description">
 
251
          <p>
 
252
Takes our cert=foo callerids and return the foo bit else nil
 
253
</p>
 
254
          <p><a class="source-toggle" href="#"
 
255
            onclick="toggleCode('M000024-source');return false;">[Source]</a></p>
 
256
          <div class="method-source-code" id="M000024-source">
 
257
<pre>
 
258
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 249</span>
 
259
249:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">certname_from_callerid</span>(<span class="ruby-identifier">id</span>)
 
260
250:                 <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">id</span> <span class="ruby-operator">=~</span> <span class="ruby-regexp re">/^cert=(.+)/</span>
 
261
251:                     <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">$1</span>
 
262
252:                 <span class="ruby-keyword kw">else</span>
 
263
253:                     <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">nil</span>
 
264
254:                 <span class="ruby-keyword kw">end</span>
 
265
255:             <span class="ruby-keyword kw">end</span>
 
266
</pre>
 
267
          </div>
 
268
        </div>
 
269
      </div>
 
270
 
 
271
      <div id="method-M000023" class="method-detail">
 
272
        <a name="M000023"></a>
 
273
 
 
274
        <div class="method-heading">
 
275
          <a href="#M000023" class="method-signature">
 
276
          <span class="method-name">client_cert_dir</span><span class="method-args">()</span>
 
277
          </a>
 
278
        </div>
 
279
      
 
280
        <div class="method-description">
 
281
          <p>
 
282
Figures out where to get client public certs from the plugin.aes.<a
 
283
href="Aes_security.html#M000023">client_cert_dir</a> config option
 
284
</p>
 
285
          <p><a class="source-toggle" href="#"
 
286
            onclick="toggleCode('M000023-source');return false;">[Source]</a></p>
 
287
          <div class="method-source-code" id="M000023-source">
 
288
<pre>
 
289
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 243</span>
 
290
243:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">client_cert_dir</span>
 
291
244:                 <span class="ruby-identifier">raise</span>(<span class="ruby-value str">&quot;No plugin.aes.client_cert_dir configuration option specified&quot;</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.client_cert_dir&quot;</span>)
 
292
245:                 <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.client_cert_dir&quot;</span>]
 
293
246:             <span class="ruby-keyword kw">end</span>
 
294
</pre>
 
295
          </div>
 
296
        </div>
 
297
      </div>
 
298
 
 
299
      <div id="method-M000019" class="method-detail">
 
300
        <a name="M000019"></a>
 
301
 
 
302
        <div class="method-heading">
 
303
          <a href="#M000019" class="method-signature">
 
304
          <span class="method-name">client_private_key</span><span class="method-args">()</span>
 
305
          </a>
 
306
        </div>
 
307
      
 
308
        <div class="method-description">
 
309
          <p>
 
310
Figures out the client private key either from MCOLLECTIVE_AES_PRIVATE or
 
311
the plugin.aes.client_private config option
 
312
</p>
 
313
          <p><a class="source-toggle" href="#"
 
314
            onclick="toggleCode('M000019-source');return false;">[Source]</a></p>
 
315
          <div class="method-source-code" id="M000019-source">
 
316
<pre>
 
317
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 212</span>
 
318
212:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">client_private_key</span>
 
319
213:                 <span class="ruby-keyword kw">return</span> <span class="ruby-constant">ENV</span>[<span class="ruby-value str">&quot;MCOLLECTIVE_AES_PRIVATE&quot;</span>] <span class="ruby-keyword kw">if</span> <span class="ruby-constant">ENV</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;MCOLLECTIVE_AES_PRIVATE&quot;</span>)
 
320
214: 
 
321
215:                 <span class="ruby-identifier">raise</span>(<span class="ruby-value str">&quot;No plugin.aes.client_private configuration option specified&quot;</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.client_private&quot;</span>)
 
322
216: 
 
323
217:                 <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.client_private&quot;</span>]
 
324
218:             <span class="ruby-keyword kw">end</span>
 
325
</pre>
 
326
          </div>
 
327
        </div>
 
328
      </div>
 
329
 
 
330
      <div id="method-M000020" class="method-detail">
 
331
        <a name="M000020"></a>
 
332
 
 
333
        <div class="method-heading">
 
334
          <a href="#M000020" class="method-signature">
 
335
          <span class="method-name">client_public_key</span><span class="method-args">()</span>
 
336
          </a>
 
337
        </div>
 
338
      
 
339
        <div class="method-description">
 
340
          <p>
 
341
Figures out the client public key either from MCOLLECTIVE_AES_PUBLIC or the
 
342
plugin.aes.client_public config option
 
343
</p>
 
344
          <p><a class="source-toggle" href="#"
 
345
            onclick="toggleCode('M000020-source');return false;">[Source]</a></p>
 
346
          <div class="method-source-code" id="M000020-source">
 
347
<pre>
 
348
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 222</span>
 
349
222:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">client_public_key</span>
 
350
223:                 <span class="ruby-keyword kw">return</span> <span class="ruby-constant">ENV</span>[<span class="ruby-value str">&quot;MCOLLECTIVE_AES_PUBLIC&quot;</span>] <span class="ruby-keyword kw">if</span> <span class="ruby-constant">ENV</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;MCOLLECTIVE_AES_PUBLIC&quot;</span>)
 
351
224: 
 
352
225:                 <span class="ruby-identifier">raise</span>(<span class="ruby-value str">&quot;No plugin.aes.client_public configuration option specified&quot;</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.client_public&quot;</span>)
 
353
226: 
 
354
227:                 <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.client_public&quot;</span>]
 
355
228:             <span class="ruby-keyword kw">end</span>
 
356
</pre>
 
357
          </div>
 
358
        </div>
 
359
      </div>
 
360
 
 
361
      <div id="method-M000010" class="method-detail">
 
362
        <a name="M000010"></a>
 
363
 
 
364
        <div class="method-heading">
 
365
          <a href="#M000010" class="method-signature">
 
366
          <span class="method-name">decodemsg</span><span class="method-args">(msg)</span>
 
367
          </a>
 
368
        </div>
 
369
      
 
370
        <div class="method-description">
 
371
          <p><a class="source-toggle" href="#"
 
372
            onclick="toggleCode('M000010-source');return false;">[Source]</a></p>
 
373
          <div class="method-source-code" id="M000010-source">
 
374
<pre>
 
375
    <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 56</span>
 
376
56:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">decodemsg</span>(<span class="ruby-identifier">msg</span>)
 
377
57:                 <span class="ruby-identifier">body</span> = <span class="ruby-identifier">deserialize</span>(<span class="ruby-identifier">msg</span>.<span class="ruby-identifier">payload</span>)
 
378
58: 
 
379
59:                 <span class="ruby-comment cmt"># if we get a message that has a pubkey attached and we're set to learn</span>
 
380
60:                 <span class="ruby-comment cmt"># then add it to the client_cert_dir this should only happen on servers</span>
 
381
61:                 <span class="ruby-comment cmt"># since clients will get replies using their own pubkeys</span>
 
382
62:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.learn_pubkeys&quot;</span>) <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.learn_pubkeys&quot;</span>] <span class="ruby-operator">==</span> <span class="ruby-value str">&quot;1&quot;</span>
 
383
63:                     <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">body</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">:sslpubkey</span>)
 
384
64:                         <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">client_cert_dir</span>
 
385
65:                             <span class="ruby-identifier">certname</span> = <span class="ruby-identifier">certname_from_callerid</span>(<span class="ruby-identifier">body</span>[<span class="ruby-identifier">:callerid</span>])
 
386
66:                             <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">certname</span>
 
387
67:                                 <span class="ruby-identifier">certfile</span> = <span class="ruby-node">&quot;#{client_cert_dir}/#{certname}.pem&quot;</span>
 
388
68:                                 <span class="ruby-keyword kw">unless</span> <span class="ruby-constant">File</span>.<span class="ruby-identifier">exist?</span>(<span class="ruby-identifier">certfile</span>)
 
389
69:                                     <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;Caching client cert in #{certfile}&quot;</span>)
 
390
70:                                     <span class="ruby-constant">File</span>.<span class="ruby-identifier">open</span>(<span class="ruby-identifier">certfile</span>, <span class="ruby-value str">&quot;w&quot;</span>) {<span class="ruby-operator">|</span><span class="ruby-identifier">f</span><span class="ruby-operator">|</span> <span class="ruby-identifier">f</span>.<span class="ruby-identifier">print</span> <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:sslpubkey</span>]}
 
391
71:                                 <span class="ruby-keyword kw">end</span>
 
392
72:                             <span class="ruby-keyword kw">end</span>
 
393
73:                         <span class="ruby-keyword kw">end</span>
 
394
74:                     <span class="ruby-keyword kw">end</span>
 
395
75:                 <span class="ruby-keyword kw">end</span>
 
396
76: 
 
397
77:                 <span class="ruby-identifier">cryptdata</span> = {<span class="ruby-identifier">:key</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:sslkey</span>], <span class="ruby-identifier">:data</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:body</span>]}
 
398
78: 
 
399
79:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@initiated_by</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:client</span>
 
400
80:                     <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:body</span>] = <span class="ruby-identifier">deserialize</span>(<span class="ruby-identifier">decrypt</span>(<span class="ruby-identifier">cryptdata</span>, <span class="ruby-keyword kw">nil</span>))
 
401
81:                 <span class="ruby-keyword kw">else</span>
 
402
82:                     <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:body</span>] = <span class="ruby-identifier">deserialize</span>(<span class="ruby-identifier">decrypt</span>(<span class="ruby-identifier">cryptdata</span>, <span class="ruby-identifier">body</span>[<span class="ruby-identifier">:callerid</span>]))
 
403
83:                 <span class="ruby-keyword kw">end</span>
 
404
84: 
 
405
85:                 <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">body</span>
 
406
86:             <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">PKey</span><span class="ruby-operator">::</span><span class="ruby-constant">RSAError</span>
 
407
87:                 <span class="ruby-identifier">raise</span> <span class="ruby-constant">MsgDoesNotMatchRequestID</span>, <span class="ruby-value str">&quot;Could not decrypt message using our key, possibly directed at another client&quot;</span>
 
408
88: 
 
409
89:             <span class="ruby-keyword kw">rescue</span> <span class="ruby-constant">Exception</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">e</span>
 
410
90:                 <span class="ruby-constant">Log</span>.<span class="ruby-identifier">warn</span>(<span class="ruby-node">&quot;Could not decrypt message from client: #{e.class}: #{e}&quot;</span>)
 
411
91:                 <span class="ruby-identifier">raise</span> <span class="ruby-constant">SecurityValidationFailed</span>, <span class="ruby-value str">&quot;Could not decrypt message&quot;</span>
 
412
92:             <span class="ruby-keyword kw">end</span>
 
413
</pre>
 
414
          </div>
 
415
        </div>
 
416
      </div>
 
417
 
 
418
      <div id="method-M000017" class="method-detail">
 
419
        <a name="M000017"></a>
 
420
 
 
421
        <div class="method-heading">
 
422
          <a href="#M000017" class="method-signature">
 
423
          <span class="method-name">decrypt</span><span class="method-args">(string, certid)</span>
 
424
          </a>
 
425
        </div>
 
426
      
 
427
        <div class="method-description">
 
428
          <p><a class="source-toggle" href="#"
 
429
            onclick="toggleCode('M000017-source');return false;">[Source]</a></p>
 
430
          <div class="method-source-code" id="M000017-source">
 
431
<pre>
 
432
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 185</span>
 
433
185:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">decrypt</span>(<span class="ruby-identifier">string</span>, <span class="ruby-identifier">certid</span>)
 
434
186:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@initiated_by</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:client</span>
 
435
187:                     <span class="ruby-ivar">@ssl</span> <span class="ruby-operator">||=</span> <span class="ruby-constant">SSL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">client_public_key</span>, <span class="ruby-identifier">client_private_key</span>)
 
436
188: 
 
437
189:                     <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-value str">&quot;Decrypting message using private key&quot;</span>)
 
438
190:                     <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@ssl</span>.<span class="ruby-identifier">decrypt_with_private</span>(<span class="ruby-identifier">string</span>)
 
439
191:                 <span class="ruby-keyword kw">else</span>
 
440
192:                     <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;Decrypting message using public key for #{certid}&quot;</span>)
 
441
193: 
 
442
194:                     <span class="ruby-identifier">ssl</span> = <span class="ruby-constant">SSL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">public_key_path_for_client</span>(<span class="ruby-identifier">certid</span>))
 
443
195:                     <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">ssl</span>.<span class="ruby-identifier">decrypt_with_public</span>(<span class="ruby-identifier">string</span>)
 
444
196:                 <span class="ruby-keyword kw">end</span>
 
445
197:             <span class="ruby-keyword kw">end</span>
 
446
</pre>
 
447
          </div>
 
448
        </div>
 
449
      </div>
 
450
 
 
451
      <div id="method-M000014" class="method-detail">
 
452
        <a name="M000014"></a>
 
453
 
 
454
        <div class="method-heading">
 
455
          <a href="#M000014" class="method-signature">
 
456
          <span class="method-name">deserialize</span><span class="method-args">(msg)</span>
 
457
          </a>
 
458
        </div>
 
459
      
 
460
        <div class="method-description">
 
461
          <p>
 
462
De-Serializes a message using the configured encoder
 
463
</p>
 
464
          <p><a class="source-toggle" href="#"
 
465
            onclick="toggleCode('M000014-source');return false;">[Source]</a></p>
 
466
          <div class="method-source-code" id="M000014-source">
 
467
<pre>
 
468
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 137</span>
 
469
137:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">deserialize</span>(<span class="ruby-identifier">msg</span>)
 
470
138:                 <span class="ruby-identifier">serializer</span> = <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.serializer&quot;</span>] <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;marshal&quot;</span>
 
471
139: 
 
472
140:                 <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;De-Serializing using #{serializer}&quot;</span>)
 
473
141: 
 
474
142:                 <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">serializer</span>
 
475
143:                     <span class="ruby-keyword kw">when</span> <span class="ruby-value str">&quot;yaml&quot;</span>
 
476
144:                         <span class="ruby-keyword kw">return</span> <span class="ruby-constant">YAML</span>.<span class="ruby-identifier">load</span>(<span class="ruby-identifier">msg</span>)
 
477
145:                     <span class="ruby-keyword kw">else</span>
 
478
146:                         <span class="ruby-keyword kw">return</span> <span class="ruby-constant">Marshal</span>.<span class="ruby-identifier">load</span>(<span class="ruby-identifier">msg</span>)
 
479
147:                 <span class="ruby-keyword kw">end</span>
 
480
148:             <span class="ruby-keyword kw">end</span>
 
481
</pre>
 
482
          </div>
 
483
        </div>
 
484
      </div>
 
485
 
 
486
      <div id="method-M000011" class="method-detail">
 
487
        <a name="M000011"></a>
 
488
 
 
489
        <div class="method-heading">
 
490
          <a href="#M000011" class="method-signature">
 
491
          <span class="method-name">encodereply</span><span class="method-args">(sender, target, msg, requestid, requestcallerid)</span>
 
492
          </a>
 
493
        </div>
 
494
      
 
495
        <div class="method-description">
 
496
          <p>
 
497
Encodes a reply
 
498
</p>
 
499
          <p><a class="source-toggle" href="#"
 
500
            onclick="toggleCode('M000011-source');return false;">[Source]</a></p>
 
501
          <div class="method-source-code" id="M000011-source">
 
502
<pre>
 
503
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 95</span>
 
504
 95:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">encodereply</span>(<span class="ruby-identifier">sender</span>, <span class="ruby-identifier">target</span>, <span class="ruby-identifier">msg</span>, <span class="ruby-identifier">requestid</span>, <span class="ruby-identifier">requestcallerid</span>)
 
505
 96:                 <span class="ruby-identifier">crypted</span> = <span class="ruby-identifier">encrypt</span>(<span class="ruby-identifier">serialize</span>(<span class="ruby-identifier">msg</span>), <span class="ruby-identifier">requestcallerid</span>)
 
506
 97: 
 
507
 98:                 <span class="ruby-identifier">req</span> = <span class="ruby-identifier">create_reply</span>(<span class="ruby-identifier">requestid</span>, <span class="ruby-identifier">sender</span>, <span class="ruby-identifier">target</span>, <span class="ruby-identifier">crypted</span>[<span class="ruby-identifier">:data</span>])
 
508
 99:                 <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:sslkey</span>] = <span class="ruby-identifier">crypted</span>[<span class="ruby-identifier">:key</span>]
 
509
100: 
 
510
101:                 <span class="ruby-identifier">serialize</span>(<span class="ruby-identifier">req</span>)
 
511
102:             <span class="ruby-keyword kw">end</span>
 
512
</pre>
 
513
          </div>
 
514
        </div>
 
515
      </div>
 
516
 
 
517
      <div id="method-M000012" class="method-detail">
 
518
        <a name="M000012"></a>
 
519
 
 
520
        <div class="method-heading">
 
521
          <a href="#M000012" class="method-signature">
 
522
          <span class="method-name">encoderequest</span><span class="method-args">(sender, target, msg, requestid, filter={}, target_agent=nil, target_collective=nil)</span>
 
523
          </a>
 
524
        </div>
 
525
      
 
526
        <div class="method-description">
 
527
          <p>
 
528
Encodes a request msg
 
529
</p>
 
530
          <p><a class="source-toggle" href="#"
 
531
            onclick="toggleCode('M000012-source');return false;">[Source]</a></p>
 
532
          <div class="method-source-code" id="M000012-source">
 
533
<pre>
 
534
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 105</span>
 
535
105:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">encoderequest</span>(<span class="ruby-identifier">sender</span>, <span class="ruby-identifier">target</span>, <span class="ruby-identifier">msg</span>, <span class="ruby-identifier">requestid</span>, <span class="ruby-identifier">filter</span>={}, <span class="ruby-identifier">target_agent</span>=<span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">target_collective</span>=<span class="ruby-keyword kw">nil</span>)
 
536
106:                 <span class="ruby-identifier">crypted</span> = <span class="ruby-identifier">encrypt</span>(<span class="ruby-identifier">serialize</span>(<span class="ruby-identifier">msg</span>), <span class="ruby-identifier">callerid</span>)
 
537
107: 
 
538
108:                 <span class="ruby-identifier">req</span> = <span class="ruby-identifier">create_request</span>(<span class="ruby-identifier">requestid</span>, <span class="ruby-identifier">target</span>, <span class="ruby-identifier">filter</span>, <span class="ruby-identifier">crypted</span>[<span class="ruby-identifier">:data</span>], <span class="ruby-ivar">@initiated_by</span>, <span class="ruby-identifier">target_agent</span>, <span class="ruby-identifier">target_collective</span>)
 
539
109:                 <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:sslkey</span>] = <span class="ruby-identifier">crypted</span>[<span class="ruby-identifier">:key</span>]
 
540
110: 
 
541
111:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.send_pubkey&quot;</span>) <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.send_pubkey&quot;</span>] <span class="ruby-operator">==</span> <span class="ruby-value str">&quot;1&quot;</span>
 
542
112:                     <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@initiated_by</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:client</span>
 
543
113:                         <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:sslpubkey</span>] = <span class="ruby-constant">File</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">client_public_key</span>)
 
544
114:                     <span class="ruby-keyword kw">else</span>
 
545
115:                         <span class="ruby-identifier">req</span>[<span class="ruby-identifier">:sslpubkey</span>] = <span class="ruby-constant">File</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">server_public_key</span>)
 
546
116:                     <span class="ruby-keyword kw">end</span>
 
547
117:                 <span class="ruby-keyword kw">end</span>
 
548
118: 
 
549
119:                 <span class="ruby-identifier">serialize</span>(<span class="ruby-identifier">req</span>)
 
550
120:             <span class="ruby-keyword kw">end</span>
 
551
</pre>
 
552
          </div>
 
553
        </div>
 
554
      </div>
 
555
 
 
556
      <div id="method-M000016" class="method-detail">
 
557
        <a name="M000016"></a>
 
558
 
 
559
        <div class="method-heading">
 
560
          <a href="#M000016" class="method-signature">
 
561
          <span class="method-name">encrypt</span><span class="method-args">(string, certid)</span>
 
562
          </a>
 
563
        </div>
 
564
      
 
565
        <div class="method-description">
 
566
          <p><a class="source-toggle" href="#"
 
567
            onclick="toggleCode('M000016-source');return false;">[Source]</a></p>
 
568
          <div class="method-source-code" id="M000016-source">
 
569
<pre>
 
570
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 162</span>
 
571
162:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">encrypt</span>(<span class="ruby-identifier">string</span>, <span class="ruby-identifier">certid</span>)
 
572
163:                 <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@initiated_by</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">:client</span>
 
573
164:                     <span class="ruby-ivar">@ssl</span> <span class="ruby-operator">||=</span> <span class="ruby-constant">SSL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">client_public_key</span>, <span class="ruby-identifier">client_private_key</span>)
 
574
165: 
 
575
166:                     <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-value str">&quot;Encrypting message using private key&quot;</span>)
 
576
167:                     <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@ssl</span>.<span class="ruby-identifier">encrypt_with_private</span>(<span class="ruby-identifier">string</span>)
 
577
168:                 <span class="ruby-keyword kw">else</span>
 
578
169:                     <span class="ruby-comment cmt"># when the server is initating requests like for registration</span>
 
579
170:                     <span class="ruby-comment cmt"># then the certid will be our callerid</span>
 
580
171:                     <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">certid</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">callerid</span>
 
581
172:                         <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;Encrypting message using private key #{server_private_key}&quot;</span>)
 
582
173: 
 
583
174:                         <span class="ruby-identifier">ssl</span> = <span class="ruby-constant">SSL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">server_public_key</span>, <span class="ruby-identifier">server_private_key</span>)
 
584
175:                         <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">ssl</span>.<span class="ruby-identifier">encrypt_with_private</span>(<span class="ruby-identifier">string</span>)
 
585
176:                     <span class="ruby-keyword kw">else</span>
 
586
177:                         <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;Encrypting message using public key for #{certid}&quot;</span>)
 
587
178: 
 
588
179:                         <span class="ruby-identifier">ssl</span> = <span class="ruby-constant">SSL</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">public_key_path_for_client</span>(<span class="ruby-identifier">certid</span>))
 
589
180:                         <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">ssl</span>.<span class="ruby-identifier">encrypt_with_public</span>(<span class="ruby-identifier">string</span>)
 
590
181:                     <span class="ruby-keyword kw">end</span>
 
591
182:                 <span class="ruby-keyword kw">end</span>
 
592
183:             <span class="ruby-keyword kw">end</span>
 
593
</pre>
 
594
          </div>
 
595
        </div>
 
596
      </div>
 
597
 
 
598
      <div id="method-M000018" class="method-detail">
 
599
        <a name="M000018"></a>
 
600
 
 
601
        <div class="method-heading">
 
602
          <a href="#M000018" class="method-signature">
 
603
          <span class="method-name">public_key_path_for_client</span><span class="method-args">(clientid)</span>
 
604
          </a>
 
605
        </div>
 
606
      
 
607
        <div class="method-description">
 
608
          <p>
 
609
On servers this will look in the aes.client_cert_dir for public keys
 
610
matching the clientid, clientid is expected to be in the format set by <a
 
611
href="Aes_security.html#M000015">callerid</a>
 
612
</p>
 
613
          <p><a class="source-toggle" href="#"
 
614
            onclick="toggleCode('M000018-source');return false;">[Source]</a></p>
 
615
          <div class="method-source-code" id="M000018-source">
 
616
<pre>
 
617
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 202</span>
 
618
202:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">public_key_path_for_client</span>(<span class="ruby-identifier">clientid</span>)
 
619
203:                 <span class="ruby-identifier">raise</span> <span class="ruby-node">&quot;Unknown callerid format in '#{clientid}'&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">clientid</span>.<span class="ruby-identifier">match</span>(<span class="ruby-regexp re">/^cert=(.+)$/</span>)
 
620
204: 
 
621
205:                 <span class="ruby-identifier">clientid</span> = <span class="ruby-identifier">$1</span>
 
622
206: 
 
623
207:                 <span class="ruby-identifier">client_cert_dir</span> <span class="ruby-operator">+</span> <span class="ruby-node">&quot;/#{clientid}.pem&quot;</span>
 
624
208:             <span class="ruby-keyword kw">end</span>
 
625
</pre>
 
626
          </div>
 
627
        </div>
 
628
      </div>
 
629
 
 
630
      <div id="method-M000013" class="method-detail">
 
631
        <a name="M000013"></a>
 
632
 
 
633
        <div class="method-heading">
 
634
          <a href="#M000013" class="method-signature">
 
635
          <span class="method-name">serialize</span><span class="method-args">(msg)</span>
 
636
          </a>
 
637
        </div>
 
638
      
 
639
        <div class="method-description">
 
640
          <p>
 
641
Serializes a message using the configured encoder
 
642
</p>
 
643
          <p><a class="source-toggle" href="#"
 
644
            onclick="toggleCode('M000013-source');return false;">[Source]</a></p>
 
645
          <div class="method-source-code" id="M000013-source">
 
646
<pre>
 
647
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 123</span>
 
648
123:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">serialize</span>(<span class="ruby-identifier">msg</span>)
 
649
124:                 <span class="ruby-identifier">serializer</span> = <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.serializer&quot;</span>] <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;marshal&quot;</span>
 
650
125: 
 
651
126:                 <span class="ruby-constant">Log</span>.<span class="ruby-identifier">debug</span>(<span class="ruby-node">&quot;Serializing using #{serializer}&quot;</span>)
 
652
127: 
 
653
128:                 <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">serializer</span>
 
654
129:                     <span class="ruby-keyword kw">when</span> <span class="ruby-value str">&quot;yaml&quot;</span>
 
655
130:                         <span class="ruby-keyword kw">return</span> <span class="ruby-constant">YAML</span>.<span class="ruby-identifier">dump</span>(<span class="ruby-identifier">msg</span>)
 
656
131:                     <span class="ruby-keyword kw">else</span>
 
657
132:                         <span class="ruby-keyword kw">return</span> <span class="ruby-constant">Marshal</span>.<span class="ruby-identifier">dump</span>(<span class="ruby-identifier">msg</span>)
 
658
133:                 <span class="ruby-keyword kw">end</span>
 
659
134:             <span class="ruby-keyword kw">end</span>
 
660
</pre>
 
661
          </div>
 
662
        </div>
 
663
      </div>
 
664
 
 
665
      <div id="method-M000022" class="method-detail">
 
666
        <a name="M000022"></a>
 
667
 
 
668
        <div class="method-heading">
 
669
          <a href="#M000022" class="method-signature">
 
670
          <span class="method-name">server_private_key</span><span class="method-args">()</span>
 
671
          </a>
 
672
        </div>
 
673
      
 
674
        <div class="method-description">
 
675
          <p>
 
676
Figures out the server private key from the plugin.aes.server_private
 
677
config option
 
678
</p>
 
679
          <p><a class="source-toggle" href="#"
 
680
            onclick="toggleCode('M000022-source');return false;">[Source]</a></p>
 
681
          <div class="method-source-code" id="M000022-source">
 
682
<pre>
 
683
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 237</span>
 
684
237:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">server_private_key</span>
 
685
238:                 <span class="ruby-identifier">raise</span>(<span class="ruby-value str">&quot;No plugin.aes.server_private configuration option specified&quot;</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.server_private&quot;</span>)
 
686
239:                 <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.server_private&quot;</span>]
 
687
240:             <span class="ruby-keyword kw">end</span>
 
688
</pre>
 
689
          </div>
 
690
        </div>
 
691
      </div>
 
692
 
 
693
      <div id="method-M000021" class="method-detail">
 
694
        <a name="M000021"></a>
 
695
 
 
696
        <div class="method-heading">
 
697
          <a href="#M000021" class="method-signature">
 
698
          <span class="method-name">server_public_key</span><span class="method-args">()</span>
 
699
          </a>
 
700
        </div>
 
701
      
 
702
        <div class="method-description">
 
703
          <p>
 
704
Figures out the server public key from the plugin.aes.server_public config
 
705
option
 
706
</p>
 
707
          <p><a class="source-toggle" href="#"
 
708
            onclick="toggleCode('M000021-source');return false;">[Source]</a></p>
 
709
          <div class="method-source-code" id="M000021-source">
 
710
<pre>
 
711
     <span class="ruby-comment cmt"># File plugins/mcollective/security/aes_security.rb, line 231</span>
 
712
231:             <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">server_public_key</span>
 
713
232:                 <span class="ruby-identifier">raise</span>(<span class="ruby-value str">&quot;No aes.server_public configuration option specified&quot;</span>) <span class="ruby-keyword kw">unless</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-value str">&quot;aes.server_public&quot;</span>)
 
714
233:                 <span class="ruby-keyword kw">return</span> <span class="ruby-ivar">@config</span>.<span class="ruby-identifier">pluginconf</span>[<span class="ruby-value str">&quot;aes.server_public&quot;</span>]
 
715
234:             <span class="ruby-keyword kw">end</span>
 
716
</pre>
 
717
          </div>
 
718
        </div>
 
719
      </div>
 
720
 
 
721
 
 
722
    </div>
 
723
 
 
724
 
 
725
  </div>
 
726
 
 
727
 
 
728
<div id="validator-badges">
 
729
  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
 
730
</div>
 
731
 
 
732
</body>
 
733
</html>
 
 
b'\\ No newline at end of file'